杰克逊展开空值对象

时间:2018-01-11 17:18:44

标签: java json jackson spring-data-rest

我们说我有Description值对象:

@JsonInclude(value = JsonInclude.Include.ALWAYS)
public class Description {
    @Column(name = "DESCRIPTION")
    private final String description;
}

Product实体:

@Entity
public class Product extends AbstractEntity<Long> {

    @JsonUnwrapped
    private final Description description;   
}

我为Description创建了自定义序列化程序:

static class DescriptionSerializer extends StdSerializer<Description> {
    DescriptionSerializer() {
        super(Description.class);
    }

    @Override
    public void serialize(Description value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
        if (value != null) {
            jgen.writeString(value.getDescription());
        } else {
            jgen.writeNull();
        }
    }
}

当我创建:

Product product = new Product(new Description("description"));

并序列化:

String result = mapper.writeValueAsString(spec);

它返回JSON:{"description":"description"}

当我创建:

Product product = new Product(null);

返回{}

但我希望{"description":null}

如果我删除@JsonUnwrapped,它会按照我预期的方式运行,但对于非空Description,它会创建嵌套对象

是否有办法以与内置Java类型相同的方式对具有空值对象的字段进行解包?

1 个答案:

答案 0 :(得分:0)

要拥有你想要的东西你应该尝试:

Product p = new Product(new Description(null));

在json中

{"description":"description"}

Description,作为其他字段的容器存在,null是description对象中Description字段的值。

这两种序列化有不同的含义。

要在代码中轻松管理它,您可以拥有如下类:

public class Product {
    private Description description;

    public Product(Description d) {
        this.description = d;
    }

    public Product() {
        this(new Description()); //all fields are null
    }

    public Product(String description) {
         return new Product(new Description(description));
    }
}

最后两个构造函数我更喜欢作为工厂方法,但它只是代码风格的问题。