5

現在、Flexjson を使用して JSON 文字列を逆シリアル化し、Android アプリのオブジェクト モデルにマップしようとしています。アプリケーションは、複数のカタログとドキュメントを含むいくつかのカタログを持つことができる、いくつかのベンダーを持つ一種のライブラリです。json は、私が影響を及ぼさない Web サービスから取得され、次のようになります。

{
    "library":{
        "vendor":[
            {
                "id":146,
                "title":"Vendor1",
                "catalog":[
                     {
                        "id":847,
                        "document":[
                            {
                                "id":1628,
                                "title":"Document",
                ...
                            },
                            {
                ...
                            }
                        ],
                        "title":"Catalog ",
                    },
                {
                ...
                }
              ]
            },
            {
            ...
            }
        ]
    }
}

したがって、各ベンダー、カタログ、ドキュメントは JSONObject で表され、すべての子カタログとドキュメントは JSONArray 内にあります。これまでのところ、Flexjson と次の逆シリアル化コードですべて正常に動作します。

LibraryResponse response = new JSONDeserializer<LibraryResponse>()
                    .use(Timestamp.class, new TimestampObjectFactory())
                    .deserialize(getLocalLibrary(), LibraryResponse.class);
return response.library;

を持つ Library オブジェクトがありList<Vendor>ます。各ベンダーにはList<Catalog>と がありList<Document>ます。

しかし残念なことに、カタログに含まれるドキュメントが 1 つだけの場合、またはカタログに含まれるカタログが 1 つだけの場合、Web サービスは JSONArray を単純な JSONObject に結び付けます。したがって、その場合のjsonは次のようになります。

"document":
    {
        "id":1628, 
        "title":"Document",
        ...
    }

現在、Flexjson は逆シリアル化の方法を認識していないため、library.vendorX.getDocument() が .vendorX.getDocument()List<HashMap>ではなくList<Document>. 1 つのアイデアは、Flexjson にそのようなケースを処理する方法を明示的に伝えることですが、どこから始めればよいかわかりません。もう 1 つの方法は、最初の json を手動で解析し、そのような JSONObjects を適切な JSONArray に置き換えることです。しかし、ライブラリはかなり深い可能性があるため、その方法はあまり良くないと思います。

こちらでご指導いただければと思います。

4

1 に答える 1

1

うーん、これはいくつかの危険なjsonマッピングが進行中です。どのバックエンドコーダーがそれをしたのですか?! #役に立たない。

コードを見ると、Flexjson はこれをすぐに処理できるようにコーディングされています。しかし、型情報をバインドに渡していないように見えるため、バインド先の型がわからないため、マップを返すだけです。それはおそらく修正されるべき バグです。良いニュースは、回避策があることです

とにかく、私が考えることができる最も簡単なことは、そのリストにObjectFactoryをインストールすることです。次に、ストリームが逆シリアル化されたときにマップまたはリストを取得するかどうかを確認できます。次に、リストにラップして、適切なデコーダーに送信できます。何かのようなもの:

LibraryResponse response = new JSONDeserializer<LibraryResponse>()
                .use(Timestamp.class, new TimestampObjectFactory())
                .use("library.vendor.values.catalog.values.document", new ListDocumentFactory() )
                .deserialize(getLocalLibrary(), LibraryResponse.class);

それで

public class ListDocumentFactory implements ObjectFactory {

     public Object instantiate(ObjectBinder context, Object value, Type targetType, Class targetClass) {
         if( value instanceof Collection ) {
             return context.bindIntoCollection((Collection)value, new ArrayList(), targetType);
         } else {
             List collection = new ArrayList();
             if( targetType instanceof ParameterizedType ) {
                 ParameterizedType ptype = (ParameterizedType) targetType;
                 collection.add( context.bind(value, ptype.getActualTypeArguments()[0]) );
             } else {
                 collection.add( context.bind( value ) );
                 return collection;
             }
         }
     }
}

それが大まかにそのバグを修正するものだと思いますが、問題も修正する必要があります。

于 2012-10-31T19:08:12.977 に答える