2010-08-10 14 views
16

estoy tratando de analizar JSON proveniente de un flujo en mi aplicación gwt 2.0.Parse json con gwt 2.0

¿Cuál es la mejor manera? ¿Debo usar javascriptobject? JSonParser? Estoy perdido con lo que estoy creando en la web porque nunca existe la versión de gwt.

String text = "{\"item\":[{\"Id\":\"1\",\"Name\":\"Bob\"},{\"Id\":\"2\",\"Name\":\"John\"},{\"Id\":\"3\",\"Name\":\"Bill\"}]}"; 

¿Cómo puedo jugar con mi lista de elementos?

Gracias de antemano por cualquier ayuda

Respuesta

33

La respuesta depende de la cantidad que confían en que JSON :) Claro, podría venir de su aplicación, pero si alguna inserte la entrada del usuario es de confianza, que se enfrentan a un posible la seguridad agujero.

Así:

  • para JSONs de fuentes confiables, utilizo JavaScript Overlay Types. Hacen la integración de JSON con GWT sin problemas y definitivamente recomendaría este enfoque. Sin embargo, internamente, esto llama a la función eval() que significa (al menos) dos cosas: el análisis JSON será extremadamente rápido (usa el código nativo de los navegadores para eso) y será posiblemente inseguro. Google para obtener más información acerca de los problemas de seguridad relacionados con JSON. JSONParser también puede analizar JSON a través de eval(), cuando invoca su método parseLenient(String jsonString), pero definitivamente es menos atractivo que JSO.
  • para que no se confía fuentes/de entrada, se debe utilizar JSONParser través JSONParser.parseStrict(String jsonString) (disponible en GWT> = 2.1) - que tendrá que escribir más código de esa manera, pero puede estar seguro de que la entrada se maneja adecuadamente. También puede buscar la integración del JSON parser from json.org "oficial" con JSO: escriba una función JSNI que devuelve el objeto analizado y lo transfiere a su JSO; en teoría, debería funcionar;) (eso es lo que GWT hace internamente con los JSO, al menos por lo que entendí)

Como para acceder a las listas de JSON, hay clases apropiadas para que: JsArray (genérica, para las listas de otra JSOs), JsArrayString, etc. Si nos fijamos en su aplicación, son sólo Contenedores JSNI alrededor de las matrices JS nativas, por lo que son muy rápidos (pero limitados, por alguna razón).


Editar en respuesta al comentario de Tim:

me escribió una clase abstracta simple que ayuda a minimizar el código repetitivo, cuando se trata de JSOs y JSON:

import com.google.gwt.core.client.JavaScriptObject; 

public abstract class BaseResponse extends JavaScriptObject { 
    // You can add some static fields here, like status codes, etc. 

    /** 
    * Required by {@link JavaScriptObject} 
    */ 
    protected BaseResponse() { } 

    /** 
    * Uses <code>eval</code> to parse a JSON response from the server 
    * 
    * @param responseString the raw string containing the JSON repsonse 
    * @return an JavaScriptObject, already cast to an appropriate type 
    */ 
    public static final native <T extends BaseResponse> T getResponse(String responseString) /*-{ 
     // You should be able to use a safe parser here 
     // (like the one from json.org) 
     return eval('(' + responseString + ')'); 
    }-*/; 
} 

A continuación, escriba su JSO real como tal:

import com.example.client.model.User; 

public class LoginResponse extends BaseResponse { 

    protected LoginResponse() { } 

    public final native String getToken() /*-{ 
     return this.t; 
    }-*/; 

    public final native int getId() /*-{ 
     return parseInt(this.u[0]); 
    }-*/; 

    // ... 

    // Helper method for converting this JSO to a POJO 
    public final User getUser() { 
     return new User(getLogin(), getName(), getLastName()); 
    } 
} 

Y finalmente en el código:

// response.getText() contains the JSON string 
LoginResponse loginResponse = LoginResponse.getResponse(response.getText()); 
//^no need for a cast \o/ 

Su JSON se parece a esto (cortesía de JSONLint, una gran validador JSON):

{ 
    "item": [ 
     { 
      "Id": "1", 
      "Name": "Bob" 
     }, 
     { 
      "Id": "2", 
      "Name": "John" 
     }, 
     { 
      "Id": "3", 
      "Name": "Bill" 
     } 
    ] 
} 

Por lo tanto, me gustaría escribir un JSO que describe los elementos de esa lista:

public class TestResponse extends BaseResponse { 

    protected TestResponse() { } 

    public final native String getId() /*-{ 
     return this.Id; 
    }-*/; 

    public final native String getName() /*-{ 
     return this.Name; 
    }-*/; 

    // Static helper for returning just the list 
    // Code untested but you should get the idea ;) 
    public static final native JsArray<TestResponse> getTestList(String json) /*-{ 
     var stuff = eval('(' + json + ')'); 
      return stuff.item; 
    }-*/; 
} 

Luego, en el código se llama TestResponse.getTestList(someJsonString) y jugar un poco con el JsArray obtiene (el TestResponse s que contiene se crean automágicamente). Genial, ¿eh? ;) Podría ser un poco confuso al principio, pero créanme, va a tener sentido una vez que comience a usarlo y es mucho más fácil que analizar a través de JSONParser> _>

+0

Gracias por su ayuda, voy para usar los tipos de superposición js. ¿Pero cómo traduciría mi texto json para obtener un cliente? En el ejemplo, usa: $ wnd.jsonData [0]; En mi caso, tengo una cadena (procedente de un RequestBuilder) – Tim

+0

funcionando perfectamente, gracias. Me perdí la función de evaluación. Saludos cordiales – Tim

+0

¿Por qué usó llaves alrededor de la cuerda en eval? En este código: 'return eval ('(' + responseString + ')');' – Davor