I have a small hierarchy of classes that I need to serialize to XML. I found a past posting(Jackson serialize list with polymorphic elements to XML) , which was useful for getting the subclasses to serialize with the proper subclass name. However, the fields of those subclasses are not being serialized. Here I will provide an example:
public abstract class Animal {}
public class Dog extends Animal{
public String breed;
public String age;
public Dog(String breed, String age) {
this.breed = breed;
this.age = age;
}
}
@JsonSerialize(using = ZooSerializer.class)
public class Zoo {
public List<Animal> animals = new ArrayList<>();
}
public class ZooSerializer extends StdSerializer<Zoo> {
public ZooSerializer(Class<Zoo> t) {
super(t);
}
public ZooSerializer() {
this(null);
}
@Override
public void serialize(Zoo zoo, JsonGenerator jg, SerializerProvider sp) throws IOException
{
jg.writeStartObject();
for (Animal animal: zoo.animals) {
jg.writeNullField(animal.getClass().getSimpleName());
}
jg.writeEndObject();
}
, then using this to test:
@Test
public void Test() {
XmlMapper xmlMapper = new XmlMapper();
try {
Zoo zoo = new Zoo();
Dog dog = new Dog("Collie", "6");
System.out.println(xmlMapper.writerWithDefaultPrettyPrinter().writeValueAsString(dog));
zoo.animals.add(dog);
System.out.println(xmlMapper.writerWithDefaultPrettyPrinter().writeValueAsString(zoo));
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
, I get the following response:
<Dog>
<breed>Collie</breed>
<age>6</age>
</Dog>
<Zoo>
<Dog/>
</Zoo>
So, I cannot figure out why the dog fields are present when streaming the dog object by itself, but not when streaming it after adding to the zoo object. I would be grateful for any ideas. Thank you.
CodePudding user response:
You can use the JsonGenerator#writeObjectField
method that serialize the Dog
pojo inside the already defined ZooSerializer#serialize
method like below:
public class ZooSerializer extends StdSerializer<Zoo> {
public ZooSerializer(Class<Zoo> t) {
super(t);
}
public ZooSerializer() {
this(null);
}
@Override
public void serialize(Zoo zoo, JsonGenerator jg, SerializerProvider sp) throws IOException {
jg.writeStartObject();
for (Animal animal: zoo.animals) {
String animalClassName = animal.getClass().getSimpleName();
jg.writeObjectField(animalClassName, animal);
}
jg.writeEndObject();
}
}
Output in your main example:
<Zoo>
<Dog>
<breed>Collie</breed>
<age>6</age>
</Dog>
</Zoo>
Due to the writing of a custom serializer in this way without the use of the JsonTypeInfo
you have to write a custom deserializer if you want to deserialize the obtained xml to a Zoo
object.