java 反序列化包含多个项目的 JSON 对象

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15060514/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 18:21:43  来源:igfitidea点击:

deserializing a JSON object with multiple items inside it

javaandroidjsongson

提问by drew moore

I'm trying to deserialize (using gson) a JSON object that looks like this:

我正在尝试反序列化(使用 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
            }
    },

How do I handle it? I don't even know what to call this - There are multiple "items" represented here, but it's not an array. When I try to deserialize it as an array, the program crashes on a "Expected Begin_Array but found Begin_Object" exception. When I try to deserialize it as a Strong object (see class below), the program runs but the fields all return null.

我该如何处理?我什至不知道该怎么称呼它 - 这里表示了多个“项目”,但它不是一个数组。当我尝试将其反序列化为数组时,程序因“预期的 Begin_Array 但发现 Begin_Object”异常而崩溃。当我尝试将其反序列化为 Strong 对象(请参阅下面的类)时,程序会运行,但所有字段都返回 null。

Here is the class I've tried to map it to:

这是我尝试将其映射到的类:

class Attachment {
int ID;
String URL;
}

the full JSON file can be seen here:

完整的 JSON 文件可以在这里看到

EDIT: SOLVED.

编辑:解决了。

@Perception's solution basically worked. It was complicated by the fact that this "element" (still would like to know what this multiple-entry/non-array json element) is embedded in a larger json object that does contain an array. Again, this JSON is not my design - it comes from the Wordpress REST API, and (as @Perception alluded to), I think the issue I've had illustrates a design flaw in it - namely that the attachments element should be an array, rather than a single object. Nonetheless,

@Perception 的解决方案基本上有效。由于这个“元素”(仍然想知道这个多条目/非数组 json 元素是什么)被嵌入到一个包含数组的更大的 json 对象中,这一事实很复杂。同样,这个 JSON 不是我的设计——它来自 Wordpress REST API,并且(正如@Perception 所暗示的那样),我认为我遇到的问题说明了其中的一个设计缺陷——即附件元素应该是一个数组,而不是单个对象。尽管如此,

Nonetheless, if anyone else ever needs to deserialize the result of a query for all posts on a given site using this API, and further needs access to the attachments on each post, here's how you do it:

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

回答by Perception

This is an example of data that probably shouldhave been serialized as an array, but was not. One solution to parsing it is to utilize a JSONObjectdirectly.

这是一个可能应该序列化为数组但没有序列化的数据示例。解析它的一种解决方案是JSONObject直接使用 a 。

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


The data canalso be viewed as a map, of id's to attachments. And it can be deserialized as such:

该数据也被看作是一个地图,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());

This is actuall

这实际上是

回答by Tamilselvan Kalimuthu

First create JSONArray from this JSONObject., then

首先从这个 JSONObject 创建 JSONArray,然后

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

By using this loop get the string values and put in a map or object that u want and add it to a ArrayList

通过使用此循环获取字符串值并放入您想要的地图或对象并将其添加到 ArrayList

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

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

And

contactList.add(map);

then you can use that values.

那么你可以使用这些值。

回答by Programmer Bruce

How do I handle it? I don't even know what to call this - There are multiple "items" represented here, but it's not an array.

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

It looks like the collection in the JSON is a natural fit for a java.util.map. So, I'd probably deserialize the JSON "attachments" into a Map<String, Atachment>. The map is then easy to iterate over, or transform the collection of Attachment values into a different type of collection, like a List<Attachment>or an Attachment[].

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

Note: The Gson User Guideincludes an example of deserializing into a Generic Collection.

注意:Gson 用户指南包含一个反序列化为通用集合的示例。