如何从 Java HTTPResponse 解析 JSON?
Posted
技术标签:
【中文标题】如何从 Java HTTPResponse 解析 JSON?【英文标题】:How do I parse JSON from a Java HTTPResponse? 【发布时间】: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。
【问题讨论】:
【参考方案1】:两件事可以更有效地完成:
-
使用
StringBuilder
而不是StringBuffer
,因为它是更快更小的兄弟。
使用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 版本不同。以上是关于如何从 Java HTTPResponse 解析 JSON?的主要内容,如果未能解决你的问题,请参考以下文章
如何从 Apache HttpClient5 的 HttpResponse 中获取响应体?
从 org.apache.http.HttpResponse 获取 HTTP 代码