2016-11-29 16 views
0

私はJacksonを使用して、java.lang.Numberを拡張するカスタム数値クラスを直列化および逆シリアル化しようとしています。以下は、Numberを拡張しないクラスのベアボーン実装です。ジャクソンの直列化とjava.lang.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 

ジャクソンは主張していないデシリアライズに失敗した読み取りにクラスを変更しかし、第二の「Number値(14169630718280903901)からデシリアライズすることが見つかりませ適しクリエイター法」と非常によく果たしています。さらに、時には失敗するだけです。

これが起こっている理由、またはジャクソンをjava.lang.Numberのクラスのインスタンスに正常にデシリアライズする方法を知っている人はいますか?

答えて

0

davidxxx実際には、シリアライズされた数値がLong.MAX_VALUEより大きい場合にのみデシリアライズが失敗するというのは間違いありません。しかし、問題はそれよりも少し深いものです。

Numberを拡張しない場合、Jacksonは通常のオブジェクトとして扱い、getter、setter、およびデフォルトのコンストラクタUnsignedNumericClass()を使用してシリアル化/逆シリアル化を行います。

UnsignedNumericClassNumberになると、toString()と文字列引数コンストラクタUnsignedNumericClass(String data)を使用して、シリアライズ/デシリアライズを行います。 String引数のコンストラクタが存在しない場合、例外がスローされることに注意してください。

私は符号なし64ビット番号を実装しているので問題の問題が発生しました。番号が符号なしなので、toString()実装では、private long dataフィールドの符号なし解釈が出力されます。

数値型をデシリアライズするときに、ジャクソンはそれが有効な数値であることを確認します。つまり、JSON文書で指定された数値がLong.MAX_VALUEより小さいかどうかをチェックします。これが当てはまらない場合は、文字列引数コンストラクタを使用するだけでなく、適切な数値を処理できるカスタムデシリアライザを使用します。カスタムデシリアライザは指定されていないため、「適切な作成者メソッドがありません」例外がスローされます。したがって、解決策は、文字列の引数のコンストラクタを使用して単純なカスタムデシリアライザを定義することです:

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で事前定義されているため、この問題はそのクラスには表示されません。

関連する問題