简体   繁体   English

如何使用Jackson反序列化空类型JSON字段

[英]How to deserialize null type JSON fields with Jackson

I'm developing a PATCH API. 我正在开发PATCH API。 If the fields are sent as JSON null value I need to save them as null . 如果字段以JSON null值发送,则需要将它们另存为null However I can't distinguish if they're sent as null or never sent. 但是我无法区分它们是作为null发送还是从不发送。

{
      "max_amount": null
}
Double maxAmount;

I have Double , Integer , Date etc. fields. 我有DoubleIntegerDate等字段。 I can deserialize them to Double.NAN , Integer.MIN_VALUE when they're really sent as null to understand if they're sent as null . 我可以在将它们真正发送为null时将它们反序列化为Double.NANInteger.MIN_VALUE ,以了解是否将它们发送为null But Deserializers don't work when the field is null . 但是,当字段为null时,反序列化器将不起作用。 Of course it's an option to send "-1" or an impossible value to define null but I didn't like this approach. 当然,可以选择发送“ -1”或一个不可能的值来定义null但我不喜欢这种方法。 I will have to agree with the clients for all types. 我将不得不同意所有类型的客户。 What's the best approach in this case? 在这种情况下最好的方法是什么?

In cases like this you should define POJO class with properties set to predefined undefined like data. 在这种情况下,您应该定义POJO类,并将其属性设置为预定义的undefined like数据。 For example, for Integer property if negative numbers are not allowed from business point of view, it could be -1 . 例如,对于Integer属性,如果从业务角度来看不允许使用负数,则它可以是-1 Then, when JSON is deserialised to POJO properties set to null override default values and you will know it was sent. 然后,当将JSON反序列化为POJO属性设置为null会覆盖默认值,并且您将知道它已发送。 There should be 3 options: 应该有3个选择:

  1. Regular value in JSON - properly deserialised to a value in POJO JSON常规值-正确反序列化为POJO的值
  2. null value in JSON - deserialised to null in POJO JSON null值-在POJO反序列化为null
  3. Not available pair key-value - default value in POJO is not overridden. 不可用对key-value POJO默认值不会被覆盖。

Below example uses Jackson in version 2.9.9 : 下面的示例在2.9.9版中使用Jackson

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;

import java.time.LocalDateTime;

public class JsonApp {

    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(new JavaTimeModule());

        String[] jsons = {
                "{\"number\":1,\"date\":\"2019-01-01T22:23:11\",\"max_amount\":4.9}",
                "{\"number\":null,\"date\":null,\"max_amount\":null}",
                "{}",
                "{\"number\":1}",
                "{\"date\":\"2019-01-01T22:23:11\"}",
                "{\"max_amount\":4.9}",
                "{\"number\":1,\"date\":null,\"max_amount\":null}"
        };
        for (String json : jsons) {
            System.out.println(json + " => " + mapper.readValue(json, Pojo.class));
        }
    }
}

class Pojo {

    private static final LocalDateTime NULL_DATE = LocalDateTime.of(1900, 1, 1, 12, 13);

    @JsonProperty("max_amount")
    private Double maxAmount = Double.MIN_VALUE;
    private Integer number = Integer.MIN_VALUE;

    @JsonFormat(shape = JsonFormat.Shape.STRING)
    private LocalDateTime date = NULL_DATE;

    public Double getMaxAmount() {
        return maxAmount;
    }

    public void setMaxAmount(Double maxAmount) {
        this.maxAmount = maxAmount;
    }

    public Integer getNumber() {
        return number;
    }

    public void setNumber(Integer number) {
        this.number = number;
    }

    public LocalDateTime getDate() {
        return date;
    }

    public void setDate(LocalDateTime date) {
        this.date = date;
    }

    @Override
    public String toString() {
        return "{" +
                "number=" + number +
                ", date=" + date +
                ", maxAmount=" + maxAmount +
                '}';
    }
}

Above code prints: 上面的代码打印:

{"number":1,"date":"2019-01-01T22:23:11","max_amount":4.9} => {number=1, date=2019-01-01T22:23:11, maxAmount=4.9}
{"number":null,"date":null,"max_amount":null} => {number=null, date=null, maxAmount=null}
{} => {number=-2147483648, date=1900-01-01T12:13, maxAmount=4.9E-324}
{"number":1} => {number=1, date=1900-01-01T12:13, maxAmount=4.9E-324}
{"date":"2019-01-01T22:23:11"} => {number=-2147483648, date=2019-01-01T22:23:11, maxAmount=4.9E-324}
{"max_amount":4.9} => {number=-2147483648, date=1900-01-01T12:13, maxAmount=4.9}
{"number":1,"date":null,"max_amount":null} => {number=1, date=null, maxAmount=null}

Of course, you should pick default values in the way it will minimise possibility of collision that client by accident send value treated as undefined by your API . 当然,您应该选择默认值,以最大程度地减少客户端偶然发送的值被API undefined的冲突可能性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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