I can't figure out why nested object aren't clearly parsed from BeanIo.
The parsing is based on "fixedlength", so positional.
Give these pojos:
@Record(minOccurs=1)
@Data
public class Address {
@Field(length=2)//,at=1)
private String prov;
@Field(length=6)//at=2)
private String city;
}
and
@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;
}
I've made this class to attempt both input and output operations to clearify the problem:
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;
}
}
Bu the input and output won't take care of nested colletion, console output looks like this:
Joe Black
Employee(firstName=Joe, addresses=null, lastName=Black)
I've tested various attempt but can't figure out. Pls point me in the right direction.
Please also refer to the Segments section of the BeanIO Reference Guide. It is too much to copy here, but a segment is used to indicate nested objects inside a @Record
. To make use of the segments you need to annotate the property List<Address>
with the @Segment
annotation and specify the collection type in this case. Your Employee
class then becomes:
@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;
}
There are various other attributes you can configure for a segment. See the documentation for more options.
PS: Not part of the problem, but you probably have a typo in your test code:
Address address2 = new Address();
address1.setCity("MILAN"); // I assume you want MILAN to be the city for address2, not address1
addresses.add(address2);