简体   繁体   中英

Jackson JSON serialization: How to ignore a nested object when all its fields are null?

I'm using Jackson and I have some JSON schema objects set up something like this:

@JsonInclude(JsonInclude.Include.NON_EMPTY)
public class Person {

    String name;
    Child child = new Child();
    Sibling sibling = new Sibling();

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

    public Child getChild() {
        return child;
    }
    public void setChild(Child child) {
        this.child = child;
    }

    public Sibling getSibling() {
        return sibling;
    }
    public void setSibling(Sibling sibling) {
        this.sibling = sibling;
    }
}

@JsonInclude(JsonInclude.Include.NON_EMPTY)
public class Child {

    String name;

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

@JsonInclude(JsonInclude.Include.NON_EMPTY)
public class Sibling {

    String name;

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

I'm attempting to ignore all fields that are null or empty, which works fine. But I also want to ignore objects with fields that are all null or empty. For example:

Person person = new Person();
person.setName("John Doe");
ObjectMapper mapper = new ObjectMapper();
String json = objectMapper.writeValueAsString(person);

The resulting JSON string is {"name":"John Doe","child":{},"sibling":{}} , but I want it to be {"name":"John Doe"} . Child and Sibling need to be initialized when Person is created so I don't want to change that. Is there a way to make Jackson treat objects with null fields as null with a custom serializer? I've seen examples of using custom serializers for specific types of objects but I need one that would work for any object.

You can achieve this in an arguably simpler way without custom serialiser(s) for Person or Child and Sibling but with CUSTOM include and passing the type of the field as filter.

First of all define correct equals methods for Child and Sibling . Then, to filter nested objects that are equal to what their default constructor would return, annotate the pertinent getters in Person like this:

@JsonInclude(value = JsonInclude.Include.CUSTOM, valueFilter = Child.class)
public Child getChild() {
    return child;
}

@JsonInclude(value = JsonInclude.Include.CUSTOM, valueFilter = Sibling.class)
public Sibling getSibling() {
    return sibling;
}

Setting valueFilter to Child.class above has the effect of creating an object with the default constructor Child emptyChild = new Child() and then to decide that another object Child child should be serialised checks that emptyChild.equals(child) is false

docs for valueFilter

In your case, I think ignoring null values on the serializer level should be enough:

mapper.setSerializationInclusion(Include.NON_EMPTY);
mapper.setSerializationInclusion(Include.NON_NULL);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM