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

时间:2015-03-10 23:30:10

标签: java jackson deserialization json-deserialization

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

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

已经尝试过:我已经搜索了DeserializationFeature枚举,但我认为没有任何内容适用。 (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..
    }

json.txt的内容。请注意,值null实际上写在文件中。它不是空的。它不是空字符串。它实际上是null。

{
  "thing" : {
    "longitude" : null,
    "latitude" : null,
    "altitude" : null
  }
}

代码

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...
}

2 个答案:

答案 0 :(得分: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;
}

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

@JsonDeserialize(using = ThingDeserializer.class)
public class Thing implements Serializable { 
            ... class code here ... 
}

注意我认为更好的答案是反序列化Double类而不是Thing类。通过反序列化Double,您可以概括从null到NaN的转换。这也将取消从字段名称中拉出节点中的特定字段。我无法弄清楚如何在有限的时间内完成这项工作,所以这对我有用。此外,反序列化实际上是由Jackson通过REST api隐式调用的,所以我不确定如何改变这些事情。我很乐意看到一个可以实现这一目标的解决方案。

答案 1 :(得分:1)

这就是我所做的:

public class DoubleDeserializer extends JsonDeserializer<Double> {

    @Override
    public Double deserialize(JsonParser parser, DeserializationContext ctxt)
            throws IOException, JsonProcessingException {

        String doubleStr = parser.getText();

        if (doubleStr.isEmpty() || doubleStr == null) {
            return null;
        }

        return new Double(doubleStr);
    }
}

然后在我的bean中:

@JsonDeserialize(using = DoubleDeserializer.class)
private Double partialPressureCO2;

希望这有帮助。