如何将 null 反序列化为 Double.NaN (Java, Jackson)

mis*_*ena 5 java jackson deserialization json-deserialization

问题: Jackson ObjectMapper 反序列化器正在将 Double 字段的空值转换为 0。我需要将它反序列化为 null 或 Double.NaN。我怎样才能做到这一点?

我是否需要编写一个将 null 映射到 Double.NaN 的自定义 Double 反序列化器?

已经尝试过:我已经搜索了 DeserializationFeature Enum,但我认为不适用。(http://fasterxml.github.io/jackson-databind/javadoc/2.0.0/com/fasterxml/jackson/databind/DeserializationFeature.html#FAIL_ON_NULL_FOR_PRIMITIVES

动机:我正在将一个 json 对象反序列化为一个自定义对象 (Thing),其代码类似于以下内容。我需要解串器将值保持为 null 或将其更改为 Double.NaN,因为我需要能够区分 0 情况(位于纬度/经度/高度 = 0)和 null/Double.NaN 情况(当这些值不可用)。

杰克逊反序列化

try {
        ObjectMapper mapper = new ObjectMapper();
        Thing t = mapper.readValue(new File("foobar/json.txt"), Thing.class);

    } catch (JsonParseException e) {
        ...do stuff..
    }
Run Code Online (Sandbox Code Playgroud)

json.txt 的内容。请注意,值 null 实际写入文件中。它不会留空。它不是空字符串。它实际上是空这个词。

{
  "thing" : {
    "longitude" : null,
    "latitude" : null,
    "altitude" : null
  }
}
Run Code Online (Sandbox Code Playgroud)

事物的代码

import java.io.Serializable;

public class Thing implements Serializable {

    private static final long serialVersionUID = 1L;

    Double latitude;
    Double longitude;
    Double altitude;

    public Thing(Double latitude, Double longitude, Double altitude) {
         this.latitude = latitude;
         this.longitude = longitude;
         this.altitude = altitude; 

    }
    ...rest of code...
}
Run Code Online (Sandbox Code Playgroud)

mis*_*ena 2

对我有用的解决方案是制作一个自定义 JSON 反序列化器,将 null 转换为 Double.NaN。调整我写的内容以匹配上面的示例代码,它看起来像这样。

public class ThingDeserializer extends JsonDeserializer<Thing> {

@Override
public Thing deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException,
        JsonProcessingException {

    Thing thingy = new Thing();

    JsonNode node = jp.getCodec().readTree(jp);
    if (node.get("latitude").isNull()) {
        thingy.setLatitude(Double.NaN);
    } else {
       thingy.setLatitude(node.get("latitude").asDouble());
    }
    if (node.get("longitude").isNull()) {
        thingy.setLongitude(Double.NaN);
    } else {
        thingy.setLongitude(node.get("longitude").asDouble());
    }
    if (node.get("altitude").isNull()) {
        thingy.setAltitude(Double.NaN);
    } else {
        thingy.setLatitude(node.get("altitude").asDouble());
    }
    return thingy;
}
Run Code Online (Sandbox Code Playgroud)

然后我通过在类声明上方添加注释来在类 Thing 中注册反序列化器。

@JsonDeserialize(using = ThingDeserializer.class)
public class Thing implements Serializable { 
            ... class code here ... 
}
Run Code Online (Sandbox Code Playgroud)

请注意,我认为更好的答案是反序列化 Double 类而不是 Thing 类。通过反序列化 Double,您可以概括从 null 到 NaN 的转换。这也将消除按字段名称从节点中提取特定字段的情况。我不知道如何在有限的时间预算内做到这一点,所以这对我有用。另外,反序列化实际上是由 Jackson 通过 REST api 隐式调用的,所以我不确定这如何/是否会改变事情。我很想看到一个能够实现这一目标的解决方案。