如何从Java HTTPResponse解析JSON?

72

我刚刚发起了一个Web请求,得到了一个HttpResponse对象。响应以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。

7个回答

84

可以更高效地完成两件事情:

  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个字节吗?显然这取决于输出的平均行大小,但批次数量很可能比每行少。 - Joe Ludwig
4
BufferedReader 内部已经缓冲了 8KB。总之,这可能是微观优化,两种方式都足够好,我更喜欢可读性更强的代码。你正在使用的习惯用法是典型的字节流用法,而不是字符流用法。PS:你为什么编辑问题将 StringBuffer 替换为 StringBuilder?现在对于第一次阅读问题的人来说,我的建议就变得没有那么有意义了 :) - BalusC
我只是更改了变量名。在原始问题的版本中,它是一个StringBuilder,但我可以看出使用名称“缓冲区”可能会使事情变得混乱。 :) - Joe Ludwig
太棒了。JSONTokener是从哪里来的?我总是找不到这些该死的jar文件。 - manafire
在此处找到了JSONArray和JSONTokener jar here - manafire
显示剩余2条评论

9
使用JSON Simple。

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

这个程序很小,没有依赖,非常适合在Android上使用。

你可以像这样做:

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

1
这相比内置的 org.json 包有什么优势? - CommonsWare
如果您熟悉org.json并且您的应用程序仅适用于Android,则它可能没有任何优势。否则,json-simple更简单易用,而且JAR文件更小(14k vs 43k)。我们在任何地方都使用它,甚至在Android上也是如此。 - ZZ Coder

5
您可以使用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;
}

refer this


2

Jackson似乎支持直接从InputStream解析JSON。我的理解是它可以在Android上运行,并且速度相当快。另一方面,它是一个额外的JAR文件,需要包含在您的应用程序中,这会增加下载和闪存大小。


0

不要做

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来自commons IO库。


0
对于Android,使用Apache的Commons IO库来处理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

-3

不需要自己编写读取循环。JsonTokener 已经内置了此功能。例如:

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

1
我找不到任何接受BufferedReader的JSONTokener构造函数,因此这个答案是误导性的。 - Ian Newson
没有接受BufferedReader的构造函数,但是有一个接受Reader的构造函数,而BufferedReader是Reader的子类。 --> org.json.JSONTokener(Reader reader) - guido
这个构造函数似乎不是Android的一部分:http://developer.android.com/reference/org/json/JSONTokener.html - Ian Newson
我从 json.org 网站获得了我的,它似乎与 Android 版本不同。 - guido

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接