2010-08-10 13 views
16

Ich versuche JSON von einem Flow in meiner gwt 2.0-Anwendung zu analysieren.Parse JSON mit gwt 2.0

Was ist der beste Weg? Sollte ich Javascriptobject verwenden? JSonParser? Ich bin verloren mit dem, was ich im Internet gründe, weil es nie die gwt-Version gibt.

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

Wie kann ich mit meiner Artikelliste spielen?

Vielen Dank im Voraus für jede Hilfe

Antwort

33

Die Antwort hängt davon ab, wie viel Vertrauen Sie, dass JSON :) Sicher, könnte es aus Ihrer Anwendung kommen, aber wenn etwas nicht vertrauenswürdigen Benutzereingabe einfügen, werden Sie eine mögliche Sicherheit mit Blick auf Loch.

So:

  • für JSONs aus vertrauenswürdigen Quellen, verwende ich JavaScript Overlay Types. Sie machen die Integration von JSON mit GWT nahtlos und ich würde diesen Ansatz definitiv empfehlen. Intern ruft dies jedoch die eval()-Funktion auf, was (mindestens) zwei Dinge bedeutet: JSON-Parsing wird extrem schnell sein (es verwendet browsereigenen Code dafür) und wird möglicherweise unsicher sein. Google für weitere Informationen zu JSON-bezogenen Sicherheitsproblemen. JSONParser kann JSON auch über eval() analysieren, wenn Sie seine Methode parseLenient(String jsonString) aufrufen, aber es ist definitiv weniger attraktiv als JSO.
  • für nicht vertrauenswürdigen Quellen/Eingang, sollten Sie JSONParser über JSONParser.parseStrict(String jsonString) (erhältlich in GWT> = 2.1) verwenden - Sie werden mehr Code auf diese Weise zu schreiben, aber Sie können sicher sein, dass die Eingabe korrekt gehandhabt wird. Sie könnten auch in die Integration der "offiziellen" JSON parser from json.org mit JSO - schreiben Sie eine JSNI Funktion, die das geparste Objekt zurück und wirft es auf Ihre JSO - in der Theorie sollte arbeiten;) (das ist, was GWT tut intern mit JSOs, zumindest von dem, was ich verstanden)

Wie für Listen in JSON, gibt es entsprechende Klassen für den Zugriff auf das: nur JsArray (generic, für Listen anderer JSOs), JsArrayString usw. Wenn man sich ihre Umsetzung, sie sind JSNI-Wrapper um die nativen JS-Arrays sind also sehr schnell (aber aus irgendeinem Grund begrenzt).


bearbeiten als Antwort auf Tims Kommentar:

schrieb ich eine einfache abstrakte Klasse, die den Standardcode zu minimieren hilft, wenn sie mit JSOs und JSON zu tun:

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

Sie dann schreibe dein aktuelles JSO als solches:

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()); 
    } 
} 
in Ihrem CodeUnd schließlich:

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

Ihre JSON wie diese (mit freundlicher Genehmigung von JSONLint, ein großen JSON-Validator) aussehen:

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

Also, würde ich eine JSO schreiben, die die Elemente von beschreibt diese Liste:

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

Dann, in Ihrem Code Sie TestResponse.getTestList(someJsonString) und spielen, um mit dernennenerhalten Sie (die TestResponse s es enthält automatisch erstellt werden). Cool, was? ;) Es ist vielleicht etwas verwirrend auf den ersten, aber glauben Sie mir, wird es Sinn machen, wenn Sie es benutzen und es ist viel einfacher als über JSONParser Parsen> _>

+0

Danke für Ihre Hilfe, ich werde js Überlagerungstypen verwenden. Aber wie würde ich meinen JSON-Text übersetzen, um einen Kunden zu bekommen? Im Beispiel verwendet er: $ wnd.jsonData [0]; In meinem Fall habe ich eine Zeichenfolge (von einem RequestBuilder) – Tim

+0

funktioniert perfekt, danke. Ich habe die Eval-Funktion verpasst. Mit freundlichen Grüßen – Tim

+0

Warum haben Sie Klammern in Eval um die Zeichenfolge verwendet? In diesem Code: 'return eval ('(' + responseString + ')');' – Davor