Jackson JSON序列化:如何在嵌套对象的所有字段均为null时忽略它?

10

我正在使用Jackson,我已经设置了一些类似于这样的JSON模式对象:

@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;
    }
}

我试图忽略所有为空的字段,这个功能正常工作。但我还想忽略所有字段都为空的对象。例如:

Person person = new Person();
person.setName("John Doe");
ObjectMapper mapper = new ObjectMapper();
String json = objectMapper.writeValueAsString(person);
生成的 JSON 字符串为 {"name":"John Doe","child":{},"sibling":{}},但我希望它只有 {"name":"John Doe"}。由于需要在创建 Person 时初始化 ChildSibling,因此不想改变该过程。是否有一种方式可以使 Jackson 将具有 null 字段的对象视为 null,并使用自定义序列化程序?我看到了针对特定类型的对象使用自定义序列化程序的示例,但我需要适用于任何对象的程序。

你需要编写一个自定义反序列化器。https://dev59.com/HlkS5IYBdhLWcg3wHDHU - Pankaj Gadge
我正在寻找序列化的解决方案,而不是反序列化,并且适用于所有对象类型。 - David DeMar
2个回答

3
您可以通过使用CUSTOM包含和传递字段类型作为筛选器的方式,在不需要PersonChildSibling自定义序列化程序的情况下,以一种可以说更简单的方式实现此目标。

首先为ChildSibling定义正确的equals方法。然后,要过滤嵌套对象,使它们等于其默认构造函数返回的内容,请像这样注释Person中相关的getter:

@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;
}

valueFilter设置为Child.class,将创建一个具有默认构造函数Child emptyChild = new Child()的对象,并决定另一个对象Child child是否应进行序列化,检查emptyChild.equals(child)是否为false。更多信息请参阅valueFilter文档

这个可以工作,但是如果你没有在Person中初始化Child或Sibling呢?即使Person在其定义中指定了NOT_EMPTY,它们两个都会返回null。 - Joselo

0
在您的情况下,我认为在序列化器级别忽略空值就足够了:
mapper.setSerializationInclusion(Include.NON_EMPTY);
mapper.setSerializationInclusion(Include.NON_NULL);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接