2010-08-10 6 views
16

Я пытаюсь разобрать JSON, исходящий из потока в моем приложении gwt 2.0.Parse json with gwt 2.0

Каков наилучший способ? Должен ли я использовать 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 также может анализировать JSON через eval(), когда вы вызываете его метод parseLenient(String jsonString), но он определенно менее привлекателен, чем JSO.
  • для ненадежных источников/вход, вы должны использовать JSONParser через JSONParser.parseStrict(String jsonString) (доступен в GWT> = 2.1) - вы должны будете писать больше кода, что путь, но вы можете быть уверены, что вход надлежащим образом. Вы также можете изучить интеграцию «официального» JSON parser from json.org с JSO - написать функцию JSNI, которая возвращает проанализированный объект и отсылает его на ваш JSO - теоретически это должно работать;) (это то, что GWT делает внутри с JSOs, по крайней мере от того, что я понял)

что касается доступа списков в формате 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 s он содержит автоматически). Круто, а? ;) Сначала может показаться немного запутанным, но поверьте мне, это будет иметь смысл, как только вы начнете его использовать, и это много проще, чем синтаксический анализ через JSONParser> _>

+0

Спасибо за вашу помощь, я собираюсь для использования типов наложения js. Но как бы я перевел свой json-текст, чтобы получить клиента? В этом примере он использует: $ wnd.jsonData [0]; В моем случае у меня есть строка (поступающая из RequestBuilder) – Tim

+0

работает отлично, спасибо. Я пропустил функцию eval. С уважением – Tim

+0

Почему вы использовали фигурные скобки вокруг строки в eval? В этом коде: 'return eval ('+ responseString +') ');' – Davor