Разбор json с gwt 2.0 - PullRequest
       25

Разбор json с gwt 2.0

17 голосов
/ 10 августа 2010

Я пытаюсь проанализировать JSON из потока в моем приложении gwt 2.0.

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

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

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

Заранее спасибо за любую помощь

1 Ответ

34 голосов
/ 10 августа 2010

Ответ зависит от того, насколько вы доверяете этому 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 делает внутренне с JSO, по крайней мере из того, что я понял)

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


Редактировать в ответ на комментарий Тима:

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...