2010-08-10 1 views
16

sto provando ad analizzare JSON proveniente da un flusso nella mia applicazione gwt 2.0.Pare json with gwt 2.0

Qual è il modo migliore? Dovrei usare javascriptobject? JSonParser? Sono perso con quello che sto fondando sul web perché non c'è mai la versione gwt.

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

Come posso giocare con il mio elenco di elementi?

Grazie in anticipo per qualsiasi aiuto

risposta

33

La risposta dipende da quanto si ha fiducia che JSON :) Certo, potrebbe essere venuta dalla vostra applicazione, ma se inserire qualche input dell'utente non attendibile, si trovano ad affrontare una possibile sicurezza buco.

Quindi:

  • per JSONs da fonti attendibili, io uso JavaScript Overlay Types. Rendono l'integrazione di JSON con GWT senza soluzione di continuità e raccomando senz'altro questo approccio. Tuttavia, internamente, questo chiama la funzione eval() che significa (almeno) due cose: l'analisi JSON sarà estremamente veloce (utilizza il codice nativo del browser per quello) e sarà probabilmente insicura. Google per ulteriori informazioni sui problemi di sicurezza relativi a JSON. JSONParser può anche analizzare JSON tramite eval(), quando si richiama il metodo parseLenient(String jsonString), ma è decisamente meno attraente di JSO.
  • per non attendibile fonti/ingresso, è necessario utilizzare JSONParser via JSONParser.parseStrict(String jsonString) (disponibile in GWT> = 2.1) - dovrete scrivere più codice in questo modo, ma si può essere sicuri che l'ingresso è gestita correttamente. Potresti anche considerare l'integrazione del "ufficiale" JSON parser from json.org con JSO - scrivere una funzione JSNI che restituisce l'oggetto analizzato e lanciarlo sul tuo JSO - in teoria è dovrebbe funzionare;) (questo è ciò che GWT fa internamente con JSOs, almeno da quello che ho capito)

per quanto riguarda l'accesso a liste in JSON, ci sono classi appropriate per questo: JsArray (generica, per gli elenchi di altri JSOs), JsArrayString, ecc Se si guarda alla loro realizzazione, sono solo I wrapper JSNI intorno agli array JS nativi, quindi sono molto veloci (ma limitati, per qualche motivo).


Modifica in risposta al commento di Tim:

ho scritto una semplice classe astratta che aiuta a ridurre al minimo il codice standard, quando si tratta di JSOs e 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 + ')'); 
    }-*/; 
} 

Poi si scrivi il tuo vero JSO in quanto tale:

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

E finalmente nel codice:

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

tuo JSON si presenta così (per gentile concessione di JSONLint, un grande JSON validatore):

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

Quindi, mi piacerebbe scrivere un OCS che descrive le voci di tale elenco:

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; 
    }-*/; 
} 

Poi, nel codice si chiama TestResponse.getTestList(someJsonString) e giocare con la JsArray (gli TestResponse s che contiene sono creati automaticamente). Fantastico, eh? ;) Potrebbe essere un po 'di confusione in un primo momento, ma credetemi, sarà un senso una volta che si inizia ad usarlo ed è molto più facile che il parsing tramite JSONParser> _>

+0

Grazie per il vostro aiuto, ho intenzione usare i tipi di sovrapposizione js. Ma come tradurrei il mio testo JSON per ottenere un cliente? Nell'esempio, usa: $ wnd.jsonData [0]; Nel mio caso ho una stringa (proveniente da un RequestBuilder) – Tim

+0

perfettamente funzionante, grazie. Ho perso la funzione eval. Con i migliori saluti – Tim

+0

Perché hai usato le parentesi graffe attorno alla stringa in eval? In questo codice: 'return eval ('(' + responseString + ')');' – Davor