2012-01-11 7 views
4

ジャクソンを使用してJSONから逆シリアル化する必要があるクラスがあります。クラス構造は次のようになります。ジャクソン:スローする代わりにプロパティを無視する

public class A { 
    public B b; 
} 

public class B { 
    public List<C> c; 
} 

public class C { 
    public String s; 
    public Long l1; 
    public Long l2; 
    public Long l3; 
} 

オブジェクトのデシリアライズはほとんどうまく動作します。 を除き、の場合、リストが空のときに誤った値を出力するバグのあるコードと相互運用しています。それは代わりに発光する、次のとおりです。

{ "b" : { "c" : [] } } 

はそれが放出される。もちろん、このすべてが理にかなって

org.codehaus.jackson.map.JsonMappingException: Can not deserialize instance of java.util.ArrayList out of START_OBJECT token 
at [Source: [[email protected]; line: 1, column: 896] (through reference chain: A["b"]->B["c"]) 

:それはこれを検出したときに

{ "b" : { "c" : {} } } 

ジャクソンは、この例外がスローされます。入力が間違っています。

ただし、の場合、空のリストはこのコードには関係ありません。それがnullなら私は気にしませんでした。それを逆シリアル化できない場合は、このプロパティを無視して(そしてnullを保存する)ジャクソンに伝える方法はありますか?

public class CListDeserializer extends JsonDeserializer<List<C>> 
{ 
    public CListDeserializer() { } 

    @Override 
    public List<C> deserialize(JsonParser arg0, 
     DeserializationContext arg1) throws IOException, 
      JsonProcessingException 
    { 
     try 
     { 
      return arg0.readValueAs(new TypeReference<List<C>>(){}); 
     } 
     catch (JsonMappingException jme) 
     { 
     } 
     return null; 
    } 
} 

そして、私はフィールドに注釈を追加した場合::

org.codehaus.jackson.map.JsonMappingException: Can not instantiate value of type [simple type, class asgard.ChangeEntry] from JSON String; no single-String constructor/factory method (through reference chain: A["b"]) 

@JsonDeserialize(using=CListDeserializer.class) 
public List<C> c; 

私が代わりにこの例外を取得

は、私は、カスタムデシリアライザを使用して試してみましたこの例外は、デシリアライズを試みるとしか発生しません彼は外側のタイプA - 私はBのために内部シリアル化された値を引き出し、それを逆シリアル化する場合、それは正常に動作します。

+0

つ以上のデータポイント:クラスBは、同じ名前を持つ列挙型のフィールドを持っています'A'の' B'への参照として 'public EnumType b'を返します。ジャクソンがインナータイプ「B」を脱直列化しようとすると、混乱しているように見え、それを「A」として逆シリアル化しようとしています –

答えて

2

カスタムデシリアライザが動作しない理由を私は考え出した:readValueAs方法は次のトークンとして}を残して、例外がトリガされ、{を消費します。これで内側のオブジェクトが閉じられ、次に遭遇する列挙値は列挙型ではなく内側の型として解析される必要があると考えられます。

私はこの明日頑張りますが、私は進むべき道はdeserialize方法では、このだと思う:

ObjectMapper om = ...; 

JsonNode node = arg0.readValueAs(JsonNode.class); 
try 
{ 
    return om.readValue(node, new TypeReference<List<C>>(){}); 
} 
catch (JsonMappingException jme) 
{ 
} 
return null; 
+0

'arg0.readValueAs(JsonNode.class)'が動作しない場合は、 'arg0.readValueAsTree()'を試してみてください。これはJsonNodeも返します。 – waxwing

+0

うん、うまくいく。 –

関連する問題