迫使jackson反序列化为特定的原始类型

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

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

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

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

然后用反序列化

 mapper.readValue(destination, Node.class); 

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

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

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

jackson2.6中有一个新function专门用于此案例:

配置ObjectMapper以使用DeserializationFeature.USE_LONG_FOR_INTS

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

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

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

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

 public class MyDeserializer extends JsonDeserializer { @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()); } } 

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

 @JsonIgnoreProperties(ignoreUnknown = true) public class Message { public Long ID; @JsonCreator private Message(Map properties) { try { this.ID = (Long) properties.get("id"); } catch (ClassCastException e) { this.ID = ((Integer) properties.get("id")).longValue(); } } } 

在我的情况下,我不想对ObjectMapper使用DeserializationFeature.USE_LONG_FOR_INTS,因为它会影响所有项目。 我使用了下一个解决方案:使用自定义反序列化器:

 import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.ObjectCodec; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonNode; import java.io.IOException; public class LongInsteadOfIntegerDeserializer extends JsonDeserializer { @Override public Object deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { ObjectCodec codec = jsonParser.getCodec(); JsonNode jsonNode = codec.readTree(jsonParser); if (jsonNode.isInt()) { return jsonNode.asLong(); } return codec.treeToValue(jsonNode, Object.class); } } 

并将其添加到Object类型的字段中:public class SomeTOWithObjectField {

  //... other fields @JsonDeserialize(using = LongInsteadOfIntegerDeserializer.class) private Object value; //... other fields } 

并且它将整数反序列化为long,但其他类型如String,boolean,double等被反序列化,因为它们应该是默认的。