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 it 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.