2010-08-10 45 views
16

我想解析來自我的gwt 2.0應用程序中的流的JSON。用gwt 2.0解析json

什麼是最好的方法?我應該使用javascriptobject嗎? JSonParser?我迷失在網上,因爲它從來沒有gwt版本。

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

我該如何玩我的物品清單?

預先感謝任何幫助

回答

33

答案取決於你多麼相信,JSON :)當然,這可能是從你的應用程序來的,但如果插入一些不信任的用戶輸入,你面對一個可能的安全孔。

所以:

  • 爲JSONs來自可信來源,我用JavaScript Overlay Types。他們使JSON與GWT無縫集成,我肯定會推薦這種方法。但是,在內部,這稱爲eval()函數,這意味着(至少)兩件事:JSON解析速度非常快(它使用瀏覽器本機代碼),並且可能不安全。 Google瞭解有關JSON相關安全問題的更多信息。 JSONParser也可以通過eval()解析JSON,當您調用parseLenient(String jsonString)方法時,但它絕對不如JSO有吸引力。
  • 爲不可信來源/輸入,你應該使用通過JSONParser.parseStrict(String jsonString)JSONParser(GWT中> = 2.1可用) - 你必須編寫更多的代碼是這樣,但你可以肯定的是,輸入被妥善處理。你也可以考慮將「官方」JSON parser from json.org與JSO整合在一起 - 編寫一個JSNI函數,返回解析對象並將其轉換爲JSO--理論上它應該工作;)(這就是GWT在內部對JSO的影響,至少從我的理解)

至於在JSON訪問列表,有適當的類爲:JsArray(通用,其他JSOs),JsArrayString,等等。如果你看看他們執行的名單,他們只是JSNI圍繞本地JS數組進行封裝,所以它們非常快(但由於某種原因而受到限制)。


編輯迴應蒂姆的評論:

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

然後你請寫下您的實際JSO:

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

最後在你的代碼:

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

您的JSON看起來像這樣(禮貌JSONLint,一個偉大的JSON驗證):

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

所以,我會寫一個JSO描述的項目該列表:

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

然後,在你的代碼中調用TestResponse.getTestList(someJsonString)和玩的JsArray你會得到(它包含的TestResponse是自動創建的)。很酷,呃? ;)這可能是一個有點混亂在第一,但相信我,它纔有意義,一旦你開始使用它,它很多比通過JSONParser解析> _>

+0

感謝您的幫助,我會更容易使用js覆蓋類型。 但是,如何翻譯我的json文本以獲得客戶?在這個例子中,他使用:$ wnd.jsonData [0]; 在我來說,我有一個字符串(從RequestBuilder推出) – Tim 2010-08-10 14:32:00

+0

完美的工作,謝謝。我錯過了eval函數。 祝你好運 – Tim 2010-08-11 10:09:38

+0

爲什麼你在eval的字符串周圍使用大括號?在此代碼: '返回的eval( '(' + responseString + ')');' – Davor 2013-05-28 16:43:03