迫使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
我最终创建了一个自定义反序列化器,因为在我的应用程序逻辑中,值只有四种不同的类型( Double
, Long
, Integer
和String
)。
我不确定这是否是最好的解决方案,但它现在有效。
public class MyDeserializer extends JsonDeserializer
我用过类似下面的东西来解决这个问题。
@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
并将其添加到Object类型的字段中:public class SomeTOWithObjectField {
//... other fields @JsonDeserialize(using = LongInsteadOfIntegerDeserializer.class) private Object value; //... other fields }
并且它将整数反序列化为long,但其他类型如String,boolean,double等被反序列化,因为它们应该是默认的。