Java 如何使用Jackson反序列化空类型JSON字段
我正在开发一个补丁API。如果字段作为Java 如何使用Jackson反序列化空类型JSON字段,java,json,null,jackson,deserialization,Java,Json,Null,Jackson,Deserialization,我正在开发一个补丁API。如果字段作为JSONnull值发送,我需要将它们保存为null。但是,我无法区分它们是作为null发送还是从未发送 { "max_amount": null } 双倍最大金额; 我有Double,Integer,Date等字段。当它们真正作为null发送时,我可以将它们反序列化为Double.NAN,Integer.MIN\u值,以了解它们是否作为null发送。但是当字段为null时,反序列化程序不工作。当然,它是一个发送“-1”的选项,或者是一个不可能
JSON
null
值发送,我需要将它们保存为null
。但是,我无法区分它们是作为null
发送还是从未发送
{
"max_amount": null
}
双倍最大金额;
我有
Double
,Integer
,Date
等字段。当它们真正作为null
发送时,我可以将它们反序列化为Double.NAN
,Integer.MIN\u值
,以了解它们是否作为null
发送。但是当字段为null
时,反序列化程序不工作。当然,它是一个发送“-1”的选项,或者是一个不可能定义null
的值,但我不喜欢这种方法。我必须同意客户的所有类型。在这种情况下,最好的方法是什么 在这种情况下,您应该定义POJO
类,并将属性设置为预定义的未定义的数据。例如,对于Integer
属性,如果从业务角度来看不允许使用负数,则它可以是-1
。然后,当JSON
反序列化为POJO
时,属性设置为null
覆盖默认值,您将知道它已发送。应该有3种选择:
JSON中的常规值
-正确反序列化为POJO中的值
JSON中的null
值-反序列化为POJO中的null
不可用对键值
-未覆盖POJO
中的默认值
下面的示例使用版本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 +
'}';
}
}
以上代码打印:
{"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}
当然,您应该选择默认值,这样可以最大限度地减少冲突的可能性,客户机意外发送的值被您的API处理为undefined
,感谢您的评论和努力。然而,我们找到了一个更好的解决方案来摆脱默认值。我们定义了一个isMaxAmountSet布尔值,并在maxAmount的setter处将其设置为true。所以,我们可以区分这个值是否在请求体中发送。