2010-05-16 19 views
69

Tengo un objeto HttpResponse para una solicitud web que acabo de hacer. La respuesta está en formato JSON, así que necesito analizarlo. Puedo hacerlo de una manera absurdamente compleja, pero parece que debe haber una mejor manera.¿Cómo analizo JSON desde una respuesta HTTP Java?

¿Es esto realmente lo mejor que puedo hacer?

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

Estoy en Android si eso hace la diferencia.

Respuesta

82

Dos cosas que se pueden hacer de manera más eficiente:

  1. Uso StringBuilder en lugar de StringBuffer ya que es el más rápido y su hermano menor.
  2. Utilice BufferedReader#readLine() para leerlo línea por línea en lugar de leerlo char por 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); 

Si el JSON es en realidad una sola línea, a continuación, también puede eliminar el bucle y el constructor.

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

¿El código de la pregunta no lo leerá 1000 bytes a la vez? Obviamente, depende del tamaño de línea promedio de la salida, pero podría ser menos lotes que uno por línea. –

+0

No, como el nombre del método ya lo insinúa, el 'BufferedReader # readLine()' lee el flujo línea por línea. Es decir. divide la secuencia en nuevas líneas. Pruébalo y experimenta tú mismo. – BalusC

+0

Derecha. Ese es mi punto. Si una línea tiene menos de 1000 caracteres en promedio usando BufferedReader # readLine() implicará más veces a través del bucle que BufferedReader # read(). (No es probable que la diferencia sea importante a menos que la salida tenga muchas líneas cortas.) –

8

Uso de JSON simple,

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

que tiene una pequeña huella, sin dependencias así que es perfecto para Android.

Usted puede hacer algo como esto,

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

¿Cuál es la ventaja de este sobre el paquete 'org.json' incorporada? – CommonsWare

+0

Si está familiarizado con org.json y su aplicación es solo para Android, probablemente no tenga ninguna ventaja. De lo contrario, json-simple es mucho más fácil de usar y el JAR es mucho más pequeño (14k vs 43k). Lo usamos en todas partes, incluso en Android. –

1

Jackson parece apoyar una cierta cantidad de JSON analizar directamente desde un InputStream. Según tengo entendido, funciona en Android y es bastante rápido. Por otro lado, es un JAR extra para incluir con su aplicación, aumentando la descarga y el tamaño de flash.

-3

No hay necesidad de hacer el circuito del lector usted mismo. El JsonTokener tiene esto incorporado. Por ejemplo,

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

No puedo encontrar ningún constructor de JSONTokener que acepte un BufferedReader, por lo tanto, esta respuesta es engañosa. –

+0

No hay un constructor que acepte un BufferedReader pero un Reader y BufferedReader es una subclase de Reader. -> org.json.JSONTokener (Reader reader) – guido

+0

Este constructor no parece ser parte de Android: http://developer.android.com/reference/org/json/JSONTokener.html –

0

En vez de hacer

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()); 

Usted puede hacer:

JSONTokener tokener = new JSONTokener(
          IOUtils.toString(response.getEntity().getContent())); 

donde IOUtils es de la biblioteca Commons IO.

0

Para Android, y el uso de Apache Commons IO Biblioteca de 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

Usted puede usar la biblioteca Gson para analizar

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

} 

aquí es el archivo JSON muestra que sea fetchd desde el servidor

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

aquí está mi clase

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

refieren this

Cuestiones relacionadas