【问题标题】:How do I parse JSON from a Java HTTPResponse?如何从 Java HTTPResponse 解析 JSON?
【发布时间】:2011-02-20 04:42:43
【问题描述】:

我有一个 HttpResponse 对象,用于我刚刚发出的 Web 请求。响应是 JSON 格式,所以我需要解析它。我可以用一种荒谬的复杂方式来做到这一点,但似乎必须有更好的方法。

这真的是我能做到的最好的吗?

    HttpResponse response; // some response object
    Reader in = new BufferedReader(
        new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
    StringBuilder builder= new StringBuilder();
    char[] buf = new char[1000];
    int l = 0;
    while (l >= 0) {
        builder.append(buf, 0, l);
        l = in.read(buf);
    }
    JSONTokener tokener = new JSONTokener( builder.toString() );
    JSONArray finalResult = new JSONArray( tokener );

如果这有什么不同的话,我使用的是 Android。

【问题讨论】:

    标签: java android json


    【解决方案1】:

    两件事可以更有效地完成:

    1. 使用StringBuilder 而不是StringBuffer,因为它是更快更小的兄弟。
    2. 使用BufferedReader#readLine() 逐行读取,而不是逐字符读取。

    HttpResponse response; // some response object
    BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
    StringBuilder builder = new StringBuilder();
    for (String line = null; (line = reader.readLine()) != null;) {
        builder.append(line).append("\n");
    }
    JSONTokener tokener = new JSONTokener(builder.toString());
    JSONArray finalResult = new JSONArray(tokener);
    

    如果 JSON 实际上是单行,那么你也可以去掉循环和构建器。

    HttpResponse response; // some response object
    BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
    String json = reader.readLine();
    JSONTokener tokener = new JSONTokener(json);
    JSONArray finalResult = new JSONArray(tokener);
    

    【讨论】:

    • 问题中的代码不会一次从流中读取 1000 个字节吗?显然,这取决于输出的平均行大小,但这很可能比每行一个批次少。
    • 不,正如方法名称已经暗示的那样,BufferedReader#readLine() 逐行读取流。 IE。它在换行符上拆分流。尝试一下,亲自体验一下。
    • 对。这就是我的观点。如果一行平均少于 1000 个字符,则使用 BufferedReader#readLine() 将涉及比 BufferedReader#read() 更多的循环次数。 (除非输出有很多短线,否则差异可能并不重要。)
    • BufferedReader 在内部已经缓冲了 8KB。毕竟,这很可能是微优化,无论哪种方式都足够好,我更喜欢更易读的代码。您使用的习语是典型的字节流,而不是字符流。 PS:您为什么编辑问题以将StringBuffer 替换为StringBuilder?现在我的建议对于第一次阅读这个问题的人来说意义不大:)
    • 我只是更改了变量名。在问题的原始版本中,它是一个 StringBuilder,但我可以看到使用“缓冲区”这个名称可能会造成混淆。 :)
    【解决方案2】:

    使用简单的 JSON,

    http://code.google.com/p/json-simple/

    占用空间小,无依赖,因此非常适合 Android。

    你可以这样做,

    Object obj=JSONValue.parse(buffer.tString());
    JSONArray finalResult=(JSONArray)obj;
    

    【讨论】:

    • 这个比内置的org.json包有什么优势?
    • 如果您熟悉 org.json 并且您的应用仅适用于 Android,它可能没有优势。否则,json-simple 使用起来更简单,JAR 也更小(14k 对 43k)。我们在任何地方都使用它,甚至在 Android 上也是如此。
    【解决方案3】:

    可以使用Gson库进行解析

    void getJson() throws IOException {
        HttpClient  httpClient = new DefaultHttpClient();
        HttpGet httpGet = new HttpGet("some url of json");
        HttpResponse httpResponse = httpClient.execute(httpGet);
        String response = EntityUtils.toString(httpResponse.getEntity());
    
        Gson gson = new Gson();
        MyClass myClassObj = gson.fromJson(response, MyClass.class);
    
    }
    

    这是从服务器获取的示例 json 文件

    {
    "id":5,
    "name":"kitkat",
    "version":"4.4"
    }
    

    这是我的课

    class MyClass{
    int id;
    String name;
    String version;
    }
    

    参考this

    【讨论】:

      【解决方案4】:

      Jackson 似乎支持直接从InputStream 解析一定数量的 JSON。我的理解是它在 Android 上运行并且相当快。另一方面,它是一个额外的 JAR,可以包含在您的应用中,从而增加下载量和闪存大小。

      【讨论】:

        【解决方案5】:

        而不是做

        Reader in = new BufferedReader(
            new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
        StringBuilder builder= new StringBuilder();
        char[] buf = new char[1000];
        int l = 0;
        while (l >= 0) {
            builder.append(buf, 0, l);
            l = in.read(buf);
        }
        JSONTokener tokener = new JSONTokener( builder.toString() );
        

        你可以这样做:

        JSONTokener tokener = new JSONTokener(
                                   IOUtils.toString(response.getEntity().getContent()) );
        

        IOUtils 来自公共 IO 库。

        【讨论】:

          【解决方案6】:

          对于 Android,并使用 Apache 的 Commons IO Library for IOUtils

          // connection is a HttpURLConnection
          InputStream inputStream = connection.getInputStream()
          ByteArrayOutputStream baos = new ByteArrayOutputStream();
          IOUtils.copy(inputStream, baos);
          JSONObject jsonObject = new JSONObject(baos.toString()); // JSONObject is part of Android library
          

          【讨论】:

            【解决方案7】:

            没有必要自己做阅读器循环。 JsonTokener 内置了这个。例如

            ttpResponse response; // some response object
            BufferedReader reader = new BufferedReader(new    
            JSONTokener tokener = new JSONTokener(reader);
            JSONArray finalResult = new JSONArray(tokener);
            

            【讨论】:

            • 我找不到任何接受 BufferedReader 的 JSONTokener 构造函数,因此这个答案具有误导性。
            • 没有构造函数接受 BufferedReader 但 Reader 和 BufferedReader 是 Reader 的子类。 --> org.json.JSONTokener(Reader reader)
            • 这个构造函数似乎不是 Android 的一部分:developer.android.com/reference/org/json/JSONTokener.html
            • 我是从 json.org 网站获得的,这似乎与 android 版本不同。
            猜你喜欢
            • 2012-10-03
            • 1970-01-01
            • 2019-02-21
            • 1970-01-01
            • 2011-06-25
            • 1970-01-01
            • 2015-03-31
            • 2015-05-16
            • 1970-01-01
            相关资源
            最近更新 更多