Bean property as array/list and inner beans
gamerover98 opened this issue · 2 comments
The problem
It is not easy to create a list or array of BeanProperty.
At the moment, I have found this solution:
@Getter @Setter // Lombok
public class Country implements ParameterizedType {
private static final Type[] TYPE_ARGUMENTS = {
String.class, // name type
Integer.TYPE, // total population type
};
private String name;
private int totalPopulation;
...
@Override
public Type[] getActualTypeArguments() {
return TYPE_ARGUMENTS;
}
@Override
public Type getRawType() {
return ItemProperty.class;
}
@Override
public Type getOwnerType() {
return null;
}
}
public static final Property<Country[]> COUNTRIES =
new PropertyBuilder.ArrayPropertyBuilder<>(
new BeanPropertyType<>(
new TypeInformation(new Country()), DefaultMapper.getInstance()),
Country[]::new)
.path("country.list")
.defaultValue(new Country[0])
.build();
Now, if you want to add other info like a bean list called "City", it won't be serialized:
@Getter @Setter // Lombok
public class City implements ParameterizedType {
private static final Type[] TYPE_ARGUMENTS = {
String.class, // city type
Integer.TYPE, // population type
};
private String name;
private int population;
...
}
@Getter @Setter // Lombok
public class Country implements ParameterizedType {
private static final Type[] TYPE_ARGUMENTS = {
String.class, // name type
Integer.TYPE, // total population type
City[].class, // the city array type
};
private String name;
private int totalPopulation;
private City[] cities;
...
}
The YAML result will be:
country.list:
- name: United States
totalPopulation: 331000000
cities: {}
But what I want is:
country.list:
- name: United States
totalPopulation: 331000000
cities:
- name: New York
population: 8400000
- name: Las Vegas
population: 646700
A solution (?)
Maybe, define a BeanListProperty that extends ListPropery and grants an easy way to add beans without map field types.
After conducting various tests, I have come to a conclusion. It is incorrect to serialize an array of Beans using the PropertyBuilder.ArrayPropertyBuilder(...)
method. Instead, it is much easier to create a Bean class that encapsulates everything. Let me explain further by referring to the example of "Country":
The World Bean class:
@Getter @Setter
public class World {
private List<Country> countries;
}
The property:
public static final Property<World> WORLD =
newBeanProperty(World.class, "world", new World());
This is probably the best solution since YAML sequences can look a bit weird without a property.
In ConfigMe 2.0, arrays or lists of a bean property type will become easier to maintain as ListPropertyType
and ArrayPropertyType
are based on an entry property type, which could be a bean property type (#230). I don't have any simple tests using a bean property so I might use this issue for adding some. Thanks!
Reminder not to implement ParameterizedType by yourself, as detailed in #354 (comment)