8

次のような JSON オブジェクトを (gson を使用して) デシリアライズしようとしています。

        "attachments": {
            "40": {
                "ID": 40,
                "URL": "http:\/\/drewmore4.files.wordpress.com\/2013\/02\/wreckit.jpg",
                "guid": "http:\/\/drewmore4.files.wordpress.com\/2013\/02\/wreckit.jpg",
                "mime_type": "image\/jpeg",
                "width": 287,
                "height": 400
            },
            "3": {
                "ID": 3,
                "URL": "http:\/\/drewmore4.files.wordpress.com\/2013\/02\/frankenweenie2bposter.jpg",
                "guid": "http:\/\/drewmore4.files.wordpress.com\/2013\/02\/frankenweenie2bposter.jpg",
                "mime_type": "image\/jpeg",
                "width": 273,
                "height": 400
            }
    },

どうすればそれを処理できますか? これを何と呼べばいいのかさえわかりません。ここには複数の「アイテム」が表されていますが、配列ではありません。配列としてデシリアライズしようとすると、プログラムは「Expected Begin_Array but found Begin_Object」例外でクラッシュします。これを Strong オブジェクト (以下のクラスを参照) としてデシリアライズしようとすると、プログラムは実行されますが、フィールドはすべて null を返します。

マップしようとしたクラスは次のとおりです。

class Attachment {
int ID;
String URL;
}

完全な JSON ファイルは次の場所で確認できます

編集:解決しました。

@Perceptionのソリューションは基本的に機能しました。この「要素」(この複数エントリ/非配列json要素が何であるかを知りたい)が、配列を含むより大きなjsonオブジェクトに埋め込まれているという事実によって複雑になりました。繰り返しますが、この JSON は私の設計ではありません - それは Wordpress REST API からのものであり、(@Perception がほの​​めかしたように) 私が抱えていた問題はその設計上の欠陥を示していると思います - つまり、添付ファイル要素は配列でなければなりません、単一のオブジェクトではなく。それにもかかわらず、

それにもかかわらず、この API を使用して特定のサイトのすべての投稿に対するクエリの結果を逆シリアル化する必要があり、さらに各投稿の添付ファイルにアクセスする必要がある場合は、次のようにします。

  private class getAll extends AsyncTask <Void, Void, JSONObject> {
    private static final String url = "https://public-api.wordpress.com/rest/v1/sites/drewmore4.wordpress.com/posts/";
    @Override
    protected JSONObject doInBackground(Void... params) {

        HttpClient httpclient = new DefaultHttpClient();
        HttpGet httpget = new HttpGet(url);
        httpget.addHeader("accept", "application/json");
        JSONObject returned = new JSONObject();
        HttpResponse response;

        try {
            response = httpclient.execute(httpget);
            HttpEntity entity = response.getEntity();

            if (entity != null) {
                InputStream instream = entity.getContent();
                String result= convertStreamToString(instream);

                returned =new JSONObject(result);                   
                instream.close();
            }
        } 
        catch (ClientProtocolException | IOException | JSONException e) { e.printStackTrace();} 

        return returned;
    }

        @Override
    protected void onPostExecute (JSONObject returned){
        Gson gson = new Gson();

//posts is the element within the JSONObject that is an array of post objects
        try {
        JSONArray posts = returned.getJSONArray("posts");

        for (int curr = 0; curr < posts.length(); curr++){
            String s = posts.get(curr).toString();

            Article a = gson.fromJson(s, Article.class);

            JSONObject attachments = new JSONObject(s).getJSONObject("attachments");
            final Iterator<String> keys = attachments.keys();
               while(keys.hasNext()) {
                    final String key = keys.next();
                    a.attached.add(gson.fromJson(attachments.getJSONObject(key).toString(), Attachment.class));
                }   
               stories.add(a);
        }

            } catch (JSONException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
4

3 に答える 3

9

これは、おそらく配列としてシリアル化されるべきであったが、そうではなかったデータの例です。それを解析するための1つの解決策は、JSONObject直接利用することです。

String json = ...;
final Gson gson = new Gson();

final List<Attachment> attachements = new ArrayList<Attachment>(64);
final JSONObject jsonObj = new JSONObject(json).getJSONObject("attachments");
final Iterator<String> keys = jsonObj.keys();
while(keys.hasNext()) {
    final String key = keys.next();
    attachements.add(gson.fromJson(jsonObj.getJSONObject(key).toString(), Attachment.class);
}

// Do something with attachements

データは、IDから添付ファイルへのマップとして表示することもできます。そしてそれはそのように逆シリアル化することができます:

final String jsonObj = new JSONObject(json).getJSONObject("attachments");
final Gson gson = new Gson();
final Map<String, Attachment> data = gson.fromJson(jsonObj.toString(),
        new TypeToken<Map<String, Attachment>>() {
        }.getType());
final List<Attachment> attachments = new ArrayList<Attachment>(data.values());

これは実際です

于 2013-02-25T05:31:49.430 に答える
2

最初にこのJSONObjectからJSONArrayを作成し、次に

for(int i = 0; i < contacts.length(); i++){
            JSONObject c = contacts.getJSONObject(i);

このループを使用して、文字列値を取得し、必要なマップまたはオブジェクトを配置して、それをArrayListに追加します。

HashMap<String, String> map = new HashMap<String, String>();

            // adding each child node to HashMap key => value
            map.put(TAG_ID, id);

contactList.add(map);

次に、その値を使用できます。

于 2013-02-25T05:29:10.840 に答える
0

どうすればそれを処理できますか? これを何と呼べばいいのかさえわかりません。ここには複数の「アイテム」が表されていますが、配列ではありません。

JSON のコレクションは、java.util.map. したがって、おそらく JSON の「添付ファイル」をMap<String, Atachment>. その後、マップを簡単に反復処理したり、Attachment 値のコレクションを や などの別のタイプのコレクションに変換しList<Attachment>たりできAttachment[]ます。

注: Gson ユーザー ガイドには、ジェネリック コレクションへの逆シリアル化の例が含まれています。

于 2013-02-25T09:55:18.223 に答える