简体   繁体   English

java.lang.Number扩展的Jackson序列化和反序列化

[英]Jackson Serialization and Deserialization of java.lang.Number Extensions

I am trying to use Jackson to serialize and deserialize a custom numeric class that extends java.lang.Number . 我正在尝试使用Jackson来序列化和反序列化扩展java.lang.Number的自定义数字类。 Below is a barebones implementation of the class without extending Number . 下面是该类的准系统实现,而没有扩展Number

import com.google.common.primitives;
public class UnsignedNumericClass {
    private long data;
    public UnsignedNumericClass(long data) {
        this.data = data;
    }
    public UnsignedNumericClass(String data) {
        this.data = UnsignedLongs.decode(data);
    }
    public UnsignedNumericClass() {}
    public void setData(long data) {this.data = data;}
    public long getData() {return data;}
    public toString() {return UnsignedLongs.toString(data);}

    public int intValue() {return (int) data;}
    public long longValue() {return data;}
    public float floatValue() {return data;}
    public double doubleValue() {return data;}
}

This plays very well with Jackson, however the second I change the class to read 这与杰克逊玩得非常好,但是第二次我将课程改为阅读

public class UnsignedNumericClass extends Number

Jackson fails to deserialize claiming "No suitable creator method found to deserialize from Number value (14169630718280903901)". Jackson未能反序列化,声称“找不到从Number值反序列化的合适的创建者方法(14169630718280903901)”。 Additionally, it only fails sometimes. 此外,它有时仅会失败。

Does anyone know why this is happening or how to make Jackson successfully deserialize to an instance of a class that extends java.lang.Number ? 有谁知道为什么会这样或如何使Jackson成功反序列化为扩展java.lang.Number的类的实例?

davidxxx was indeed right that deserialization was only failing when the serialized number was greater than Long.MAX_VALUE . davidxxx确实是对的,只有当序列号大于Long.MAX_VALUE时,反序列化才会失败。 The problem runs a little deeper than that though. 问题比这更深。

When UnsignedNumericClass does not extend Number , Jackson treats it as an ordinary object and serializes/deserializes via getters, setters, and the default constructor UnsignedNumericClass() . UnsignedNumericClass不扩展Number ,Jackson会将其视为普通对象,并通过getter,setter和默认构造函数UnsignedNumericClass()序列化/反序列化。

Once UnsignedNumericClass extends Number , Jackson changes to serialize/deserialize via toString() and the String-argument constructor UnsignedNumericClass(String data) . 一旦UnsignedNumericClass扩展Number ,Jackson便会通过toString()和String参数构造函数UnsignedNumericClass(String data)进行序列化/反序列化。 Note that an exception will be thrown if a String-argument constructor does not exist. 请注意,如果不存在字符串参数构造函数,则将引发异常。

I was experiencing the questioned issue because I am implementing an unsigned 64-bit number. 我遇到了一个问题,因为我正在实现一个无符号的64位数字。 Because the number is unsigned, my toString() implementation prints the unsigned interpretation of the private long data field. 因为数字是无符号的,所以我的toString()实现打印了private long data字段的无符号解释。

When deserializing numeric types, Jackson performs a check to make sure that it is a valid number. 反序列化数字类型时,Jackson会执行检查以确保它是有效数字。 That is, it checks if the number given in the JSON document is less than Long.MAX_VALUE . 也就是说,它检查JSON文档中给定的数字是否小于Long.MAX_VALUE If this is not the case, it relies on a custom deserializer instead of just using my String-argument constructor which could handle the number just fine. 如果不是这种情况,则它依赖于自定义反序列化器,而不仅仅是使用我的String-argument构造函数,该构造函数可以很好地处理数字。 Since no custom deserializer is specified, it throws the "no suitable creator method" exception. 由于未指定自定义反序列化器,因此它将引发“没有合适的创建者方法”异常。 Therefore the solution is to define a simple custom deserializer that uses the String-argument constructor: 因此,解决方案是定义一个简单的自定义反序列化器,该反序列化器使用String-argument构造函数:

public class CustomDeserializer extends StdDeserializer<UnsignedNumericClass> {
    public CustomDeserializer(){super(null);}
    public CustomDeserializer(Class<?> c){super(c);}
    public UnsignedNumericClass deserialize(JsonParser jsonParser, DeserializationContext context) throws IOException{
        return new UnsignedNumericClass(jsonParser.getText());
}

Then we specify to Jackson to use this deserializer via the @JsonDeserialize() annotation: 然后,我们通过@JsonDeserialize()注释指定Jackson使用此反序列化器:

@JsonDeserialize(using=CustomDeserializer.class)
public class UnsignedNumericClass extends Number

I think a custom deserializer for BigInteger is predefined in Jackson so this issue does not appear for that class. 我认为在Jackson中预定义了BigInteger的自定义解串器,因此该类不会出现此问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM