2012-01-20 9 views
7

私はジャクソン用のカスタムデシリアライザを作成しようとしています。ジェネリック(ジェネリックではなくあらゆるタイプで動作するという意味でジェネリック)にしたいと思います。カスタムジャクソンデシリアライザ現在のフィールドクラスへのアクセス

しかし、私はどのように非直列化されているフィールドの型にハンドルを取得するのか分からないようです。

例えば、私は次のような何かをしているよ:

@Override 
public MyObject deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { 

     Class c = <get type of current field> 
     // do something with that type 
     return new SubclassOfC(somedata based on c); 
} 

それは特に私が苦労している現在のフィールドのGETタイプ一部です。

編集:それはtokまで...

+0

...現在のフィールドのJava型を取得します。 )?またはJSON値をマッピングする 'MyObject'に同じ名前のJavaフィールドの型ですか? –

+0

後者は、Javaフィールドのタイプです。 – monkjack

答えて

2

私はObjectMapperにデシリアライザの実装を追加することで、私の問題を解決しました。たとえば

Deserializers d = new Deserializers.Base() { 

    @Override 
    public JsonDeserializer<?> findEnumDeserializer(Class<?> type, DeserializationConfig config, BeanDescription beanDesc, BeanProperty property) 
        throws JsonMappingException { 
       if (property.getType().getContentType() != null) 
        return new EnumDeserializer(property.getType().getContentType().getRawClass()); 
       return new EnumDeserializer(property.getType().getRawClass()); 
      } 

     }; 
     mapper.setDeserializerProvider(mapper.getDeserializerProvider().withAdditionalDeserializers(d)); 

これは、別々の列挙型ごとにインスタンス化された私のカスタムEnumDeserializerを返します。

+0

私はしばらく時間を節約できましたが、imoはenumデシリアライザを使用しません。すべての種類の恐ろしい廃止予定、あなた自身で書くのが簡単です。 – MikePatel

+0

私はちょうどこの設定を追加したいと思っていました。新しいジャックソンAPIのDeserializersはあまりにも大嫌いです。 gist経由で提供される例:https://gist.github.com/patelm5/9268866 – MikePatel

0

大まかに言えば、そして例外なくキャッチし、エラーチェック私が興味を持ってJavaフィールドのタイプです

JsonToken tok = jp.nextValue(); 

Field field = findField(jp.getCurrentName()); 

Class<?> fc = field.getType(); 

if(fc == int.class) { 
    field.setInt(this, jp.getIntValue()); 
} // handle all the primitive types and String in the same way, then... 
} ... else if(tok == JsonToken.START_ARRAY) { 
    if(fc.isArray()) { 
     // Load into an array 
    } else if(Collection.class.isAssignableFrom(fc)) { 
     // Load into a collection 
    } else { 
     // throw 
    } 
} else if(tok == JsonToken.START_OBJECT) { 
    // Recursively create that object from the JSON stream 
} 

...とループEND_OBJECTです。名前で現在のクラスの検索するに:

Field findField(String name) { 
    for(Class<?> c = getClass(); c != null; c = c.getSuperclass()) { 
     for(Field field : c.getDeclaredFields()) { 
      if(field.getName().equals(name)) { 
       return field; 
      } 
     } 
    } 
} 
+0

デシリアライザのクラス内でfindFieldを調べるのではなく、デシリアライザがアンマーシャリングするために作成されたクラスではありませんか? – monkjack

3

あなたはしないでください - あなたはそれをデシリアライズすることが期待されているどのタイプを知ることデシリアライザを構築する必要があるので、デシリアライザは、種類によって登録されています。

一般的なデシリアライザを登録する場合は、ContextualDeserializerを実装することで、より動的なものにすることができます。そのcreateContextual()メソッドはBeanProperty引数で呼び出され、プロパティの名前(プロパティで参照されないルート値の場合はnullでもかまいません)や型(宣言された型)などのプロパティを確認できます。 このメソッドは新しいインスタンスを返します(元のデシリアライザはすべてのプロパティで共有されるため変更しないでください)。必要なすべての追加情報が設定されています。

+0

これは良い答えでした。残念ながら、デニリアライザをクラスEnumで登録すると、ジャクソンはカスタムクラスとは話しませんが、enumデシリアライザでビルドされているようです。これは、自分のエンティティ内のすべてのenum型に自分のenumデシリアライザを登録する必要があることを意味します。 – monkjack

+2

デシリアライザの登録時には、デシリアライザを登録する特定のタイプに適用されます。すべてのenum型を扱うために何かを作成したい場合、代わりに 'Deserializers'を実装し、それを登録する必要があります:enum型に対して新しいデシリアライザが必要になるたびに呼び出される' findEnumDeserializer() 'コールバック – StaxMan

+0

デシリアライズするクラスのBeanPropertyオブジェクトを作成するにはどうすればよいですか? –

0

私はこれをこのように解決しました。

あなたはJSON値の型(オブジェクト、配列、文​​字列、int型、などを意味するか、 "現在のフィールドの種類" によって、

@Override 
public Enum deserialize(JsonParser jsonparser, DeserializationContext context) throws IOException, JsonProcessingException { 
    System.out.println("EnumDeserializer ...."); 
    Field field = findField(jsonparser.getCurrentName(), jsonparser.getCurrentValue().getClass()); 
    Class<?> javaType = field.getType(); 
    return null; 
} 

public Field findField(String name, Class<?> c) { 
    for (; c != null; c = c.getSuperclass()) { 
     for (Field field : c.getDeclaredFields()) { 
      if (Modifier.isStatic(field.getModifiers())) { 
       continue; 
      } 
      if (field.getName().equals(name)) { 
       return field; 
      } 
     } 
    } 
    return null; 
} 

関連する問題