Подтвердить что ты не робот

Parse json с gwt 2.0

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

Каков наилучший способ? Должен ли я использовать javascriptobject? JSonParser? Я потерял то, что я основал в Интернете, потому что никогда не было версии gwt.

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

Как я могу играть с моим списком элементов?

Заранее благодарим за помощь

4b9b3361

Ответ 1

Ответ зависит от того, насколько вы доверяете JSON:) Конечно, это может произойти из вашего приложения, но если вы вставляете какой-то ненадежный пользовательский ввод, вы сталкиваетесь с возможной дырой в безопасности.

Итак:

  • для JSON из надежных источников, я использую Типы перекрытия JavaScript. Они делают интеграцию JSON с GWT бесшовной, и я определенно рекомендую этот подход. Однако внутренне это вызывает функцию eval(), которая означает (по крайней мере) две вещи: синтаксический разбор JSON будет чрезвычайно быстрым (для этого используется собственный код браузеров) и будет, вероятно, небезопасным. Google для получения дополнительной информации о связанных с JSON проблемах безопасности. JSONParser также может анализировать JSON через eval(), когда вы вызываете его parseLenient(String jsonString), но он определенно менее привлекателен, чем JSO.
  • для ненадежных источников/ввода, вы должны использовать JSONParser через JSONParser.parseStrict(String jsonString) (доступно в GWT >= 2.1) - вам придется писать больше кода таким образом, но вы можете быть уверены, что вход правильно обработан. Вы также можете изучить интеграцию "официального" JSON-парсера из json.org с JSO - написать JSNI, которая возвращает анализируемый объект и передает его в JSO - теоретически он должен работать;) (что GWT делает внутри с JSOs, по крайней мере, из того, что я понял)

Что касается доступа к спискам в JSON, для этого существуют соответствующие классы: JsArray (общий для списков других JSOs), JsArrayString и т.д. Если вы посмотрите на их реализацию, это всего лишь обертки JSNI вокруг собственных массивов JS, поэтому они очень быстрые (но ограниченные, по какой-то причине).


Изменить в ответ на комментарий Tim:

Я написал простой абстрактный класс, который помогает свести к минимуму код шаблона при работе с 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 → >