杰克逊序列化和java.lang.Number扩展的反序列化

时间:2016-11-29 14:38:32

标签: java serialization jackson

我正在尝试使用Jackson序列化和反序列化扩展java.lang.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;}
}

这对杰克逊来说非常好,但是第二次我把课程改为

public class UnsignedNumericClass extends Number

杰克逊没有反序列化声称“没有找到合适的创建者方法从数值反序列化(14169630718280903901)”。此外,它有时只会失败。

有谁知道为什么会这样,或者如何让杰克逊成功反序列化为扩展java.lang.Number的类的实例?

1 个答案:

答案 0 :(得分:0)

davidxxx确实是正确的,当序列化数量大于Long.MAX_VALUE时,反序列化才会失败。问题比这更深入。

UnsignedNumericClass未扩展Number时,杰克逊将其视为普通对象,并通过getter,setter和默认构造函数UnsignedNumericClass()进行序列化/反序列化。

一旦UnsignedNumericClass扩展Number,杰克逊就会通过toString()和字符串参数构造函数UnsignedNumericClass(String data)更改为序列化/反序列化。请注意,如果String-argument构造函数不存在,则抛出异常。

我遇到了质疑问题,因为我正在实现一个无符号的64位数字。由于该数字是无符号的,因此我的toString()实现会打印private long data字段的无符号解释。

在反序列化数字类型时,Jackson会执行检查以确保它是有效数字。也就是说,它会检查JSON文档中给出的数字是否小于Long.MAX_VALUE。如果不是这种情况,它依赖于自定义反序列化器,而不是仅仅使用我的String-argument构造函数,它可以很好地处理数字。由于未指定自定义反序列化器,因此会抛出“无合适的创建者方法”异常。因此,解决方案是定义一个使用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());
}

然后我们通过@JsonDeserialize()注释指定杰克逊使用这个反序列化器:

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

我认为BigInteger的自定义反序列化程序是在Jackson中预定义的,所以这个问题不适用于该类。