Android JsonReader无法迭代json数组

时间:2013-04-08 01:56:49

标签: android json jsonreader

我正在玩JsonReader这是Android中的流式JSON解析器,我遇到了一个问题,即解析器不会遍历json数组中的所有项目,它只会返回第一个项目

这是我用来解析的代码:

private ArrayList<Result> readResultsArray(JsonReader reader) throws IOException {
    ArrayList<Result> results = new ArrayList<Result>();

    reader.beginObject();
    while (reader.hasNext()) {
        String name = reader.nextName();
        if (name.equals("results")){
            reader.beginArray();
            while (reader.hasNext()) {
                results.add(readResult(reader));
            }
            reader.endArray();
        } else {
            reader.skipValue();
        }
    }
    reader.endObject();

    return results;
}

我确信方法readResult(reader)会解析并返回数组中的第一个对象而没有任何问题。

但是读者似乎只是“忽略”了数组中的第二个对象。

以下是readResult(reader)方法:

    private Result readResult(JsonReader reader) throws IOException {

        String from_user = null, 
                from_user_id_str = null, 
                from_user_name = null,
                text = null;
        Geo geo = null;
        URL profile_image_url = null;

        reader.beginObject();
        while (reader.hasNext()) {
            String name = reader.nextName();
            if (name.equals("from_user")){

                from_user = reader.nextString();
                Log.i(TAG, from_user);
            } else if (name.equals("from_user_id_str")) {

                from_user_id_str = reader.nextString();
                Log.i(TAG, from_user_id_str);
            } else if (name.equals("from_user_name")) {

                from_user_name = reader.nextString();
                Log.i(TAG, from_user_name);
            } else if (name.equals("geo")) {

                reader.beginObject();

                while(reader.hasNext()) {
//                      String s = reader.nextName();
                        if (name.equals("coordinates")) {
                            reader.beginArray();
                            double latitude = 0;
                            double longitude = 0;
                            while (reader.hasNext()) {
                                latitude = reader.nextDouble();
                                longitude = reader.nextDouble();
                                Log.i(TAG, latitude + ", " + longitude);
                            geo = new Geo(latitude, longitude);
                        }
                        reader.endArray();
                    } else {
                        reader.skipValue();
                    }
                }
                reader.endObject();

            } else if (name.equals("profile_image_url")) {

                profile_image_url = new URL(reader.nextString());

            } else if (name.equals("text")) {

                text = reader.nextString();
                Log.i(TAG, text);
            } else {

                reader.skipValue();

            }

        }
        reader.endObject();


        return new Result(from_user, from_user_id_str, from_user_name, text, geo, profile_image_url);
    }

}

这是我试图解析的JSON:

(这是Twitter搜索响应,原始回复如下所示,Link

{
  "completed_in": 0.067,
  "max_id": 320160565840457730,
  "max_id_str": "320160565840457730",
  "page": 1,
  "query": "%E5%90%83",
  "refresh_url": "?since_id=320160565840457730&q=%E5%90%83&geocode=51.483372%2C-3.190826%2C200mi",
  "results": [
    {
      "created_at": "Fri, 05 Apr 2013 13:06:41 +0000",
      "from_user": "missmanchu",
      "from_user_id": 359296258,
      "from_user_id_str": "359296258",
      "from_user_name": "miss manchu ",
      "geo": null,
      "location": "London, United Kingdom",
      "id": 320160565840457730,
      "id_str": "320160565840457730",
      "iso_language_code": "ja",
      "metadata": {
        "result_type": "recent"
      },
      "profile_image_url": "http://a0.twimg.com/profile_images/3470783234/6ae4049d90a052c7a9c7f86ec804e523_normal.jpeg",
      "profile_image_url_https": "https://si0.twimg.com/profile_images/3470783234/6ae4049d90a052c7a9c7f86ec804e523_normal.jpeg",
      "source": "&lt;a href=&quot;http://twitter.com/download/iphone&quot;&gt;Twitter for iPhone&lt;/a&gt;",
      "text": "RT @lougirlie: Delish Taiwanese-style bao by @missmanchu for lunch. 好吃! http://t.co/clRznskvqe"
    },
    {
      "created_at": "Fri, 05 Apr 2013 11:45:09 +0000",
      "from_user": "lougirlie",
      "from_user_id": 154974289,
      "from_user_id_str": "154974289",
      "from_user_name": "Louise Chow",
      "geo": {
        "coordinates": [
          51.5216788595,
          -0.1420583511
        ],
        "type": "Point"
      },
      "id": 320140044142772224,
      "id_str": "320140044142772224",
      "iso_language_code": "ja",
      "metadata": {
        "result_type": "recent"
      },
      "place": {
        "full_name": "Westminster",
        "id": "548c2b8e3921a85a",
        "type": "CITY"
      },
      "profile_image_url": "http://a0.twimg.com/profile_images/1750994903/photo_3__4__normal.JPG",
      "profile_image_url_https": "https://si0.twimg.com/profile_images/1750994903/photo_3__4__normal.JPG",
      "source": "&lt;a href=&quot;http://twitter.com&quot;&gt;Twitter for  iPhone&lt;/a&gt;",
      "text": "Delish Taiwanese-style bao by @missmanchu for lunch. 好吃! http://t.co/clRznskvqe"
    },
    {
      "created_at": "Fri, 05 Apr 2013 10:09:25 +0000",
      "from_user": "geleikai",
      "from_user_id": 351512769,
      "from_user_id_str": "351512769",
      "from_user_name": "geleikai",
      "geo": null,
      "location": "53.762824,-2.707418",
      "id": 320115951339200512,
      "id_str": "320115951339200512",
      "iso_language_code": "zh",
      "metadata": {
        "result_type": "recent"
      },
      "profile_image_url": "http://a0.twimg.com/profile_images/3110335584/545b94d39e1628d747428c73a8052bf8_normal.jpeg",
      "profile_image_url_https": "https://si0.twimg.com/profile_images/3110335584/545b94d39e1628d747428c73a8052bf8_normal.jpeg",
      "source": "&lt;a href=&quot;http://www.wechatapp.com&quot;&gt;WeChat App&lt;/a&gt;",
      "text": "吃过午饭,前往阿姆斯特丹 http://t.co/LbQ0Jh7Mfp"
    },
    {
      "created_at": "Thu, 04 Apr 2013 10:15:05 +0000",
      "from_user": "hpfly",
      "from_user_id": 60939059,
      "from_user_id_str": "60939059",
      "from_user_name": "0C哈根达斯",
      "geo": null,
      "location": "53.805042,-1.544011",
      "id": 319754991692824576,
      "id_str": "319754991692824576",
      "iso_language_code": "zh",
      "metadata": {
        "result_type": "recent"
      },
      "profile_image_url": "http://a0.twimg.com/profile_images/3251267049/c56ca4cb888736299548e5454a9d923b_normal.jpeg",
      "profile_image_url_https": "https://si0.twimg.com/profile_images/3251267049/c56ca4cb888736299548e5454a9d923b_normal.jpeg",
      "source": "&lt;a href=&quot;http://fanfou.com&quot;&gt;fanfou2.0&lt;/a&gt;",
      "text": "现在对谈恋爱一点欲望都没有,更多的欲望是告诉我,我内心希望独享一个人的时光。现在特别希望晚睡,而且是晚上一个人吃着宵夜,看着电视。#如果生活可以这么单纯就好了##当然这也是晚睡的牵强理由#"
    },
    {
      "created_at": "Wed, 03 Apr 2013 15:47:50 +0000",
      "from_user": "cushingliu",
      "from_user_id": 87816289,
      "from_user_id_str": "87816289",
      "from_user_name": "Cushing",
      "geo": {
        "coordinates": [
          0.0,
          0.0
        ],
        "type": "Point"
      },
      "id": 319476345325359104,
      "id_str": "319476345325359104",
      "iso_language_code": "zh",
      "metadata": {
        "result_type": "recent"
      },
      "place": {
        "full_name": "Batu Ampar",
        "id": "ddc693317ed3f226",
        "type": "CITY"
      },
      "profile_image_url": "http://a0.twimg.com/profile_images/3269471232/f89db3764b70bada908ab340a9fb9c85_normal.jpeg",
      "profile_image_url_https": "https://si0.twimg.com/profile_images/3269471232/f89db3764b70bada908ab340a9fb9c85_normal.jpeg",
      "source": "&lt;a href=&quot;http://tapbots.com/tweetbot&quot;&gt;Tweetbot for iOS&lt;/a&gt;",
      "text": "有妈妈做饭吃的感觉真好"
    }
  ],
  "results_per_page": 15,
  "since_id": 0,
  "since_id_str": "0"
}

我唯一感兴趣的部分是"results",它是一个包含两个对象的数组。

仔细观察Android Developers - JsonReader以及nice tutorial中的示例后,我发现我的与他们的基本没什么区别。

我的代码出了什么问题?为什么它不能用于json数组呢?

更新

粘贴readResult(reader)

的代码

1 个答案:

答案 0 :(得分:6)

您没有考虑将导致原始代码异常的空地理类型。使用peek()检查是否为空。我修改了代码来处理这个问题并打印出两个对象。

class MyReader
{
    public void readBegin(JsonReader reader)
    {
        try
        {
            reader.beginObject();
            while (reader.hasNext())
            {
                String name = reader.nextName();
                if (name.equals("results"))
                {
                    reader.beginArray();
                    while (reader.hasNext())
                    {
                        read(reader);
                    }
                    reader.endArray();
                }
                else
                {
                    reader.skipValue();
                }
            }
            reader.endObject();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    public void read(JsonReader reader) throws Exception
    {

        String from_user = null, from_user_id_str = null, from_user_name = null, text = null;
        URL profile_image_url = null;

        reader.beginObject();
        while (reader.hasNext())
        {
            String name = reader.nextName();
            if (name.equals("from_user"))
            {
                from_user = reader.nextString();
                System.out.println(from_user);
            }
            else if (name.equals("from_user_id_str"))
            {

                from_user_id_str = reader.nextString();
            }
            else if (name.equals("from_user_name"))
            {

                from_user_name = reader.nextString();
            }
            else if (name.equals("geo"))
            {
                if (reader.hasNext())
                {
                    JsonToken peek = reader.peek();
                    if (peek == JsonToken.NULL)
                    {
                        reader.skipValue();
                    }
                    else
                    {
                        reader.beginObject();
                        while (reader.hasNext())
                        {
                            // String s = reader.nextName();
                            if (name.equals("coordinates"))
                            {
                                reader.beginArray();
                                double latitude = 0;
                                double longitude = 0;
                                while (reader.hasNext())
                                {
                                    latitude = reader.nextDouble();
                                    longitude = reader.nextDouble();
                                }
                                reader.endArray();
                            }
                            else
                            {
                                reader.skipValue();
                            }
                        }
                        reader.endObject();
                    }
                }

            }
            else if (name.equals("profile_image_url"))
            {

                profile_image_url = new URL(reader.nextString());

            }
            else if (name.equals("text"))
            {

                text = reader.nextString();
            }
            else
            {
                reader.skipValue();
            }
        }
        reader.endObject();
    }