2012-03-22 12 views
53

JSONからデシリアライズするのに興味のあるJavaクラスMyPojoがあります。私は、特別なMixInクラス、MyPojoDeMixInを設定して、デシリアライズを手助けしました。 MyPojoには、intStringのインスタンス変数と、適切なゲッターとセッターが組み合わされています。私のテストクライアントでJSONをArrayListに逆シリアル化する<POJO>ジャクソンを使用する

public abstract class MyPojoDeMixIn { 
    MyPojoDeMixIn(
     @JsonProperty("JsonName1") int prop1, 
     @JsonProperty("JsonName2") int prop2, 
     @JsonProperty("JsonName3") String prop3) {} 
} 

私は次の操作を行いますが、型の不一致に関連JsonMappingExceptionがありますので、もちろん、それはコンパイル時には動作しません:MyPojoDeMixInは次のようになります。

ObjectMapper m = new ObjectMapper(); 
m.getDeserializationConfig().addMixInAnnotations(MyPojo.class,MyPojoDeMixIn.class); 
try { ArrayList<MyPojo> arrayOfPojo = m.readValue(response, MyPojo.class); } 
catch (Exception e) { System.out.println(e) } 

私は、私はそれでだけArrayList<MyPojo>を持つ「レスポンス」オブジェクトを作成することで、この問題を軽減することができることを承知していますが、その後、私は私が返すようにしたいすべての単一のタイプのためにこれらの多少の無駄なオブジェクトを作成する必要があります。

私はJacksonInFiveMinutesでもオンラインで見ていましたが、Map<A,B>の内容を理解するのにひどい時間がありました。あなたが言うことができない場合、私はJavaに全く新しいもので、Obj-Cのバックグラウンドから来ています。彼らは、具体的に言及:

をPOJOと「シンプル」タイプへの結合に加えて、1つの 追加のバリエーションがあります:ジェネリック(入力された)コンテナに結合することが。 このケースでは、 Collection.class(コンパイルはしません)のようなものを使用できないようにする、いわゆるタイプ消去のタイプ (Javaによって幾分後方互換性のある互換性を実装するために使用されます)のため特別な処理が必要です。だから、

あなたが使用する必要があります地図にデータをバインドしたい場合:私はArrayListに直接デシリアライズするにはどうすればよい

Map<String,User> result = mapper.readValue(src, new TypeReference<Map<String,User>>() { }); 

答えて

101

TypeReferenceラッパーを使用すると、リストに直接的に逆シリアル化できます。方法例:

public static <T> T fromJSON(final TypeReference<T> type, 
     final String jsonPacket) { 
    T data = null; 

    try { 
     data = new ObjectMapper().readValue(jsonPacket, type); 
    } catch (Exception e) { 
     // Handle the problem 
    } 
    return data; 
} 

こうして使用される:

final String json = ""; 
Set<POJO> properties = fromJSON(new TypeReference<Set<POJO>>() {}, json); 

TypeReference Javadoc

+0

あなたの答えは、組み込みの 'TypeReference'のサポートを使用する方法についての彼らの情報に関連すると思われる - 私はちょうどそれを行う方法を得ることはありませんが...どのようにその手順については、上記の私の編集を参照してください。ジェネリック医薬品を使用する。 –

+0

それは関連しています。しかし、これは生産現場のコードからのスニペットです。あなたのmixinについては忘れて、私が示したコードを使用してください(ただしPOJOは実際のbeanクラスの名前に置き換えてください)。 – Perception

+0

あなたのコードはコンパイルされましたが、 'arrayList.toString()'に 'NullPointerException'を出力しようとすると実行時例外が発生します。私は 'POJO'がそのプロパティの命名規則に準拠していない、つまりWebサービスがProp1Memberを返し、オブジェクトにProp1があることが原因であると考えられます。これが私がmixinsを使って始めている唯一の本当の理由です。そのため、純粋なオブジェクトに '@ JsonProperty'の宣言を入れる必要はありません。 –

3

私も同じ問題を抱えています。私はArrayListに変換されるjsonを持っています。

アカウントはこのようになります。

Account{ 
    Person p ; 
    Related r ; 

} 

Person{ 
    String Name ; 
    Address a ; 
} 

上記のすべてのクラスには適切な注釈が付けられています。 TypeReference>(){} を試しましたが、動作していません。

それは私にArraylistを与えますが、ArrayListには、最終的な値を含むいくつかのリンクされたハッシュマップを含むlinkedHashMapがあります。

public T unmarshal(String responseXML,String c) 
{ 
    ObjectMapper mapper = new ObjectMapper(); 

    AnnotationIntrospector introspector = new JacksonAnnotationIntrospector(); 

    mapper.getDeserializationConfig().withAnnotationIntrospector(introspector); 

    mapper.getSerializationConfig().withAnnotationIntrospector(introspector); 
    try 
    { 
     this.targetclass = (T) mapper.readValue(responseXML, new TypeReference<ArrayList<T>>() {}); 
    } 
    catch (JsonParseException e) 
    { 
     e.printStackTrace(); 
    } 
    catch (JsonMappingException e) { 
     e.printStackTrace(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 

    return this.targetclass; 
} 

は私が最終的に問題を解決し、以下のよう

私のコードです。次のように私は、ArrayListに直接JSON文字列にリストを変換することができる午前:

ObjectMapper objectMapper = new ObjectMapper(); 
MyPojo[] pojos = objectMapper.readValue(json, MyPojo[].class); 

あなたはすべての面倒を避けるため、この方法:

JsonMarshallerUnmarshaller<T>{ 

    T targetClass ; 

    public ArrayList<T> unmarshal(String jsonString) 
    { 
     ObjectMapper mapper = new ObjectMapper(); 

     AnnotationIntrospector introspector = new JacksonAnnotationIntrospector(); 

     mapper.getDeserializationConfig().withAnnotationIntrospector(introspector); 

     mapper.getSerializationConfig().withAnnotationIntrospector(introspector); 
     JavaType type = mapper.getTypeFactory(). 
        constructCollectionType(ArrayList.class, targetclass.getClass()) ; 
     try 
     { 
     Class c1 = this.targetclass.getClass() ; 
     Class c2 = this.targetclass1.getClass() ; 
      ArrayList<T> temp = (ArrayList<T>) mapper.readValue(jsonString, type); 
     return temp ; 
     } 
     catch (JsonParseException e) 
     { 
     e.printStackTrace(); 
     } 
     catch (JsonMappingException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

    return null ; 
    } 

} 
48

もう一つの方法は、例えば、タイプとして配列を使用することですあなたが本当にリストが必要な場合は、配列を常にリストに変換することができます:

List<MyPojo> pojoList = Arrays.asList(pojos); 

IMHOこれははるかに読みやすくなります。

そして、それは実際のリストであるようにするには(つまり、修正することができ、Arrays.asList()の制限を参照)そしてちょうど次の操作を行います

List<MyPojo> mcList = new ArrayList<>(Arrays.asList(pojos)); 
+2

これは受け入れられた答えであり、 – dic19

+0

合意^これはもっと役に立ちました – cstaikos

7

をこのバリアントは、よりシンプルかつエレガントに見えます。

CollectionType typeReference = 
    TypeFactory.defaultInstance().constructCollectionType(List.class, Dto.class); 
List<Dto> resultDto = objectMapper.readValue(content, typeReference); 
関連する問題