2010-05-16 3 views
69

У меня есть объект HttpResponse для веб-запроса, который я только что сделал. Ответ в формате JSON, поэтому мне нужно его разобрать. Я могу сделать это абсурдно сложным способом, но похоже, что должен быть лучший способ.Как разобрать JSON из Java HTTPResponse?

Это действительно лучшее, что я могу сделать?

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 байт за раз? Очевидно, это зависит от среднего размера строки вывода, но это может быть намного меньше партий, чем по одной строке. –

+0

Нет, поскольку имя метода уже намекает, 'BufferedReader # readLine()' считывает поток по строкам. То есть он разбивает поток на строки новой строки. Попробуйте и испытайте себя. – BalusC

+0

Справа. Это моя точка зрения. Если в среднем строка меньше 1000 символов с использованием BufferedReader # readLine() будет включать в себя больше времени через цикл, чем BufferedReader # read(). (Не то, чтобы разница, по-видимому, имела значение, если на выходе не было много коротких строк.) –

8

Использование JSON Простое,

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

Который имеет небольшой ножной печати, никаких зависимостей поэтому он идеально подходит для Android.

Вы можете сделать что-то вроде этого,

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

Что такое преимущество над этим встроенным в 'org.json' пакете? – CommonsWare

+0

Если вы знакомы с org.json, и ваше приложение предназначено только для Android, у него, вероятно, нет никакого преимущества. В противном случае json-simple намного проще использовать, а JAR намного меньше (14k против 43k). Мы используем его везде, даже на Android. –

1

Jackson кажется, поддерживает некоторое количество JSON синтаксического анализа прямо из InputStream. Я понимаю, что он работает на 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

Я не могу найти конструктор JSONTokener, который принимает BufferedReader, поэтому этот ответ вводит в заблуждение. –

+0

Нет конструктора, который принимает BufferedReader, но Reader и BufferedReader являются подклассом Reader. -> org.json.JSONTokener (Reader reader) – guido

+0

Этот конструктор, похоже, не является частью Android: http://developer.android.com/reference/org/json/JSONTokener.html –

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

Смежные вопросы