迫使杰克逊反序列化为特定的原始类型

时间:2021-09-09 18:04:49

I am serializing and deserializing following domain object to JSON using Jackson 1.8.3

我使用Jackson 1.8.3将以下域对象序列化和反序列化为JSON

public class Node {
    private String key;
    private Object value;
    private List<Node> children = new ArrayList<Node>();
    /* getters and setters omitted for brevity */
}

Object is then serialized and deserialized using following code

然后使用以下代码对对象进行序列化和反序列化

ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(destination, rootNode);

And then later deserialized with

然后用反序列化

mapper.readValue(destination, Node.class);

The original values of the object are either Strings, Doubles, Longs or Booleans. However, during serialization and deserialization Jackson transforms Long values (such as 4) to Integers.

对象的原始值是Strings,Doubles,Longs或Booleans。但是,在序列化和反序列化期间,Jackson将Long值(例如4)转换为Integers。

How can I "force" Jackson to deserialize numeric non-decimal values to Long instead of Integer?

我如何“强制”杰克逊将数字非十进制值反序列化为Long而不是Integer?

4 个解决方案

#1


7  

If type is declared as java.lang.Object, Jackson uses 'natural' mapping which uses Integer if value fits in 32 bits. Aside from custom handlers you would have to force inclusion of type information (either by adding @JsonTypeInfo next to field / getter; or by enabling so-called "default typing").

如果type被声明为java.lang.Object,那么Jackson使用'自然'映射,如果值适合32位,则使用Integer。除了自定义处理程序之外,您还必须强制包含类型信息(通过在field / getter旁边添加@JsonTypeInfo;或者通过启用所谓的“默认类型”)。

#2


19  

There is a new feature in Jackson 2.6 specifically for this case:

杰克逊2.6中有一个新功能专门用于此案例:

configure the ObjectMapper to use DeserializationFeature.USE_LONG_FOR_INTS

配置ObjectMapper以使用DeserializationFeature.USE_LONG_FOR_INTS

see https://github.com/FasterXML/jackson-databind/issues/504

请参阅https://github.com/FasterXML/jackson-databind/issues/504

cowtowncoder pushed a commit that closed this issue on May 19, 2015 Fix #504 and #797

cowtowncoder在2015年5月19日推出了一个关闭此问题的提交修复#504和#797

#3


4  

I ended up creating a custom deserializer, since in my application logic there are only four different types for values (Double, Long, Integer and String).

我最终创建了一个自定义反序列化器,因为在我的应用程序逻辑中,值只有四种不同的类型(Double,Long,Integer和String)。

I'm not sure if this is the best possible solution but it works for now.

我不确定这是否是最好的解决方案,但它现在有效。

public class MyDeserializer extends JsonDeserializer<Object> {

@Override
public Object deserialize(JsonParser p, DeserializationContext ctxt)
        throws IOException, JsonProcessingException {
    try {
        Long l = Long.valueOf(p.getText());
        return l;
    } catch (NumberFormatException nfe) {
      // Not a Long
    }
    try {
      Double d = Double.valueOf(p.getText());
      return d;
    } catch (NumberFormatException nfe) {
      // Not a Double
    }
    if ("TRUE".equalsIgnoreCase(p.getText())
          || "FALSE".equalsIgnoreCase(p.getText())) {
      // Looks like a boolean
      return Boolean.valueOf(p.getText());
    }
    return String.valueOf(p.getText());
  }
}

#4


2  

I've used something like the below to work around this problem.

我用过类似下面的东西来解决这个问题。

@JsonIgnoreProperties(ignoreUnknown = true)
public class Message {
    public Long ID;

    @JsonCreator
    private Message(Map<String,Object> properties) {
        try {
            this.ID = (Long) properties.get("id");
        } catch (ClassCastException e) {
            this.ID = ((Integer) properties.get("id")).longValue();
        }
    }
}

#1


7  

If type is declared as java.lang.Object, Jackson uses 'natural' mapping which uses Integer if value fits in 32 bits. Aside from custom handlers you would have to force inclusion of type information (either by adding @JsonTypeInfo next to field / getter; or by enabling so-called "default typing").

如果type被声明为java.lang.Object,那么Jackson使用'自然'映射,如果值适合32位,则使用Integer。除了自定义处理程序之外,您还必须强制包含类型信息(通过在field / getter旁边添加@JsonTypeInfo;或者通过启用所谓的“默认类型”)。

#2


19  

There is a new feature in Jackson 2.6 specifically for this case:

杰克逊2.6中有一个新功能专门用于此案例:

configure the ObjectMapper to use DeserializationFeature.USE_LONG_FOR_INTS

配置ObjectMapper以使用DeserializationFeature.USE_LONG_FOR_INTS

see https://github.com/FasterXML/jackson-databind/issues/504

请参阅https://github.com/FasterXML/jackson-databind/issues/504

cowtowncoder pushed a commit that closed this issue on May 19, 2015 Fix #504 and #797

cowtowncoder在2015年5月19日推出了一个关闭此问题的提交修复#504和#797

#3


4  

I ended up creating a custom deserializer, since in my application logic there are only four different types for values (Double, Long, Integer and String).

我最终创建了一个自定义反序列化器,因为在我的应用程序逻辑中,值只有四种不同的类型(Double,Long,Integer和String)。

I'm not sure if this is the best possible solution but it works for now.

我不确定这是否是最好的解决方案,但它现在有效。

public class MyDeserializer extends JsonDeserializer<Object> {

@Override
public Object deserialize(JsonParser p, DeserializationContext ctxt)
        throws IOException, JsonProcessingException {
    try {
        Long l = Long.valueOf(p.getText());
        return l;
    } catch (NumberFormatException nfe) {
      // Not a Long
    }
    try {
      Double d = Double.valueOf(p.getText());
      return d;
    } catch (NumberFormatException nfe) {
      // Not a Double
    }
    if ("TRUE".equalsIgnoreCase(p.getText())
          || "FALSE".equalsIgnoreCase(p.getText())) {
      // Looks like a boolean
      return Boolean.valueOf(p.getText());
    }
    return String.valueOf(p.getText());
  }
}

#4


2  

I've used something like the below to work around this problem.

我用过类似下面的东西来解决这个问题。

@JsonIgnoreProperties(ignoreUnknown = true)
public class Message {
    public Long ID;

    @JsonCreator
    private Message(Map<String,Object> properties) {
        try {
            this.ID = (Long) properties.get("id");
        } catch (ClassCastException e) {
            this.ID = ((Integer) properties.get("id")).longValue();
        }
    }
}