反序列化其中包含多个项的JSON对象

时间:2013-02-25 05:09:35

标签: java android json gson

我正在尝试反序列化(使用gson)一个看起来像这样的JSON对象:

        "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但发现Begin_Object”异常时崩溃。当我尝试将其反序列化为Strong对象(请参阅下面的类)时,程序会运行但字段都返回null。

以下是我尝试将其映射到的课程:

class Attachment {
int ID;
String URL;
}

可以看到完整的JSON文件here:

编辑:已解决。

@ Perception的解决方案基本上有效。很复杂的是,这个“元素”(仍然想知道这个多入口/非数组json元素是什么)嵌入在一个包含数组的较大json对象中。同样,这个JSON不是我的设计 - 它来自Wordpress REST API,并且(如@P​​erception所暗示的),我认为我已经解决了它的一个设计缺陷 - 即附件元素应该是一个数组而不是单个对象。但是,

尽管如此,如果其他人需要使用此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();
            }

3 个答案:

答案 0 :(得分:9)

这是一个数据示例,可能 已被序列化为数组,但事实并非如此。解析它的一个解决方案是直接使用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());

这是实际的

答案 1 :(得分: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);

然后你可以使用这些值。

答案 2 :(得分:0)

  

我该如何处理?我甚至不知道该怎么称呼 - 这里有多个“项目”,但它不是数组。

看起来JSON中的集合非常适合java.util.map。所以,我可能会将JSON“附件”反序列化为Map<String, Atachment>。然后,地图很容易迭代,或将附件值集合转换为不同类型的集合,如List<Attachment>Attachment[]

注意:The Gson User Guide包含反序列化为通用集合的示例。