如何从Java HTTPResponse解析JSON?


71

我有一个用于刚刚发出的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上。

Answers:


83

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

  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()读取操作将逐行读取流。即,它在换行符上拆分流。试试看,亲身体验。
BalusC 2010年

对。这就是我的意思。如果使用BufferedReader#readLine()平均每行少于1000个字符,则通过循环的时间将比BufferedReader#read()多。(除非输出中有很多短线,否则差异可能并不重要。)
Joe Ludwig 2010年

4
BufferedReader内部已经缓存在8KB。毕竟,这可能是微优化,无论哪种方式都足够好,我希望在此之上更可读的代码。您使用的惯用语通常用于字节流,而不用于字符流。PS:为什么你编辑的问题,以取代StringBufferStringBuilder?现在,我的建议对那些初次阅读该问题的人来说意义不大:)
BalusC 2010年

我只是更改了变量名。它是问题的原始版本中的StringBuilder,但我可以看到在哪里使用名称“ buffer”可能会引起混淆。:)
乔·路德维希

9

使用JSON简单,

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

占地面积小,没有依赖关系,因此非常适合Android。

你可以做这样的事情,

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

1
与内置org.json软件包相比,这有什么优势?
CommonsWare 2010年

如果您熟悉org.json并且您的应用程序仅适用于Android,则它可能没有优势。否则,json-simple更加易于使用,而JAR则小得多(14k vs 43k)。我们甚至在Android上到处都使用它。
ZZ编码器2010年

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;
}

参考这个


2

Jackson似乎直接支持来自的大量JSON解析InputStream。我的理解是,它可以在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的任何构造函数,因此此答案有误导性。
伊恩·纽森

没有接受BufferedReader的构造函数,但Reader是一个阅读器,并且BufferedReader是Reader的子类。-> org.json.JSONTokener(Reader reader)
guido

这个构造函数似乎不是Android的一部分:developer.android.com/reference/org/json/JSONTokener.html
Ian Newson,2012年

我是从json.org网站获得的,它似乎与android版本不同。
Guido 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.