Home > Software design >  Jackson - can't get fields to serialize from within a wrapping class that is using a custom jac
Jackson - can't get fields to serialize from within a wrapping class that is using a custom jac

Time:01-26

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.

  • Related