Маршалирование и демаршалирование вложенного списка фиксированной длины BeanIo

Я не могу понять, почему вложенный объект не анализируется четко из BeanIo.

Разбор основан на «фиксированной длине», поэтому позиционно.

Дайте эти пожо:

@Record(minOccurs=1) 
@Data
public class Address {
  
  @Field(length=2)//,at=1)
  private String prov;
  @Field(length=6)//at=2)
  private String city; 
}

и

@Record(minOccurs=1) 
@Data
public class Employee { 
    @Field(length=6)//,at=1)
    private String firstName; 
    private List<Address> addresses; 
    @Field(length=6)//at=2)
    private String lastName; 
}

Я сделал этот класс, чтобы попытаться выполнить операции ввода и вывода, чтобы устранить проблему:

public class BeanioTest {

    public static void main(String[] args) {
        Employee emp = new Employee();
        emp.setFirstName("Joe");
        emp.setLastName("Black");

        List<Address> addresses = new ArrayList<>();

        Address address1 = new Address();

        address1.setCity("PARIS");
        addresses.add(address1);

        Address address2 = new Address();

        address2.setCity("MILAN");
        addresses.add(address2);

        emp.setAddresses(addresses);
        String marshalled = marshaller(  emp);
        System.out.println(marshalled);


        Employee empUnm = unmarshaller(marshalled);

        System.out.println(empUnm.toString());
    } 

    public static Employee unmarshaller(String emp) {
        StreamFactory factory = StreamFactory.newInstance();

        StreamBuilder builder = new StreamBuilder("s1")
                .format("fixedlength") 
                .addRecord(Employee.class)
                .addRecord(Address.class);

        factory.define(builder);

        Unmarshaller unmarshaller = factory.createUnmarshaller("s1"); 
        Employee unmarshalled = (Employee) unmarshaller.unmarshal(emp); 
        return unmarshalled;     

    }

    public static String marshaller(Employee emp) {

        StreamFactory factory = StreamFactory.newInstance();

        StreamBuilder builder = new StreamBuilder("Tm")
                .format("fixedlength") 
                .addRecord(Employee.class)
                .addRecord(Address.class);

        factory.define(builder);

        Marshaller marshaller = factory.createMarshaller("Tm"); 
        String marshalled = marshaller.marshal(emp).toString(); 
        return marshalled;   

    }
}

Но ввод и вывод не будут заботиться о вложенной коллекции, вывод консоли выглядит так:

Joe   Black 
Employee(firstName=Joe, addresses=null, lastName=Black)

Я пробовал разные попытки, но не могу понять. Пожалуйста, укажите мне правильное направление.

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
0
25
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Также см. раздел Сегменты Справочного руководства по BeanIO. Копировать здесь слишком много, но сегмент используется для обозначения вложенных объектов внутри @Record. Чтобы использовать сегменты, вам нужно аннотировать свойство List<Address> аннотацией @Segment и указать тип коллекции в этом случае. Тогда ваш класс Employee станет:

@Data
@Record(minOccurs = 1)
@SuppressWarnings("javadoc")
public class Employee {

  @Field(length = 6)// ,at=1)
  private String firstName;
  @Segment(collection = List.class)
  private List<Address> addresses;
  @Field(length = 6)// at=2)
  private String lastName;
}

Существуют различные другие атрибуты, которые вы можете настроить для сегмента. Дополнительные параметры см. в документации.

PS: Не является частью проблемы, но у вас, вероятно, есть опечатка в тестовом коде:

  Address address2 = new Address();
  address1.setCity("MILAN"); // I assume you want MILAN to be the city for address2, not address1
  addresses.add(address2);

Да, была опечатка, исправлю. Кстати, большое спасибо, в документации BeanIo четко не нашел.

Black.Jack 06.04.2022 22:55

Другие вопросы по теме