2010-05-16 107 views
69

我有一個HttpResponse對象,用於我剛剛提出的Web請求。響應是JSON格式,所以我需要解析它。我可以用一種荒謬複雜的方式做到這一點,但似乎必須有更好的辦法。如何從Java 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上,如果這有什麼區別。

回答

82

兩件事情:

  1. 使用StringBuilder而不是StringBuffer,因爲它的速度更快和弟弟。
  2. 使用BufferedReader#readLine()逐行讀取而不是通過字符char讀取。

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); 
+0

問題中的代碼不會一次讀取1000字節的流嗎?顯然它取決於產量的平均線大小,但很可能少於每行一個批次。 – 2010-05-16 21:51:39

+0

不,由於方法名稱已經提示,BufferedReader#readLine()會逐行讀取流。即它在新行上拆分流。嘗試一下,親身體驗一下。 – BalusC 2010-05-16 21:58:05

+0

沒錯。這是我的觀點。如果一行使用BufferedReader#平均少於1000個字符,readLine()將涉及比BufferedReader#read()更多的遍歷循環。 (不是說差別可能很重要,除非輸出有很多短線。) – 2010-05-16 22:02:49

8

使用JSON簡單,

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

其中有一個小的足跡,沒有依賴性,因此是完美的Android。

你可以做這樣的事情,

可以更有效地完成
Object obj=JSONValue.parse(buffer.tString()); 
JSONArray finalResult=(JSONArray)obj; 
+1

什麼是該上內置'org.json'包中的優勢呢? – CommonsWare 2010-05-16 21:52:53

+0

如果您熟悉org.json並且您的應用僅適用於Android,則可能沒有優勢。否則,json-simple更簡單易用,而且JAR要小得多(14k vs 43k)。我們在任何地方都使用它,即使在Android上。 – 2010-05-16 23:51:44

1

Jackson似乎支持從InputStream直解析JSON的一些量。我的理解是,它運行在Android上,速度相當快。另一方面,它是一個額外的JAR包含在您的應用程序,增加下載和閃光燈的大小。

-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的構造函數,因此這個答案是誤導性的。 – 2012-02-21 22:26:49

+0

沒有接受BufferedReader的構造函數,但Reader和BufferedReader是Reader的子類。 - > org.json.JSONTokener(讀者閱讀器) – guido 2012-02-22 09:05:16

+0

這個構造函數似乎並不是Android的一部分:http://developer.android.com/reference/org/json/JSONTokener.html – 2012-02-22 11:38:06

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是公地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

可以使用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文件,該文件是從服務器fetchd

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

這是我的班級

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

參考this