Home > Mobile >  Can't get fields to serialize from within a wrapping class that is using a custom Jackson seria
Can't get fields to serialize from within a wrapping class that is using a custom Jackson seria

Time:01-27

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.

  • Related