用gwt 2.0解析json

Tim*_*Tim 17 gwt json

我正在尝试解析来自我的gwt 2.0应用程序中的流的JSON.

什么是最好的方法 ?我应该使用javascriptobject吗?JSonParser?我迷失了我在网上创建的东西,因为从来没有gwt版本.

String text = "{\"item\":[{\"Id\":\"1\",\"Name\":\"Bob\"},{\"Id\":\"2\",\"Name\":\"John\"},{\"Id\":\"3\",\"Name\":\"Bill\"}]}";
Run Code Online (Sandbox Code Playgroud)

我怎样才能玩我的物品清单?

在此先感谢您的帮助

Igo*_*mer 34

答案取决于您对JSON的信任程度:)当然,它可能来自您的应用程序,但如果插入一些不受信任的用户输入,您将面临可能的安全漏洞.

所以:

  • 对于来自可靠来源的JSON,我使用JavaScript覆盖类型.他们将JSON与GWT无缝集成,我肯定会推荐这种方法.但是,在内部,这会调用eval()函数,这意味着(至少)两件事:JSON解析将非常快(它使用浏览器本机代码)并且可能是不安全的.Google了解有关JSON相关安全问题的更多信息.当你调用它的方法时,JSONParser也可以解析JSON ,但它肯定不如JSO那么有吸引力.eval()parseLenient(String jsonString)
  • 对于不受信任的源/输入,您应该使用JSONParservia JSONParser.parseStrict(String jsonString)(在GWT> = 2.1中可用) - 您必须以这种方式编写更多代码,但您可以确保输入得到妥善处理.您还可以考虑将json.org中的"官方" JSON解析器与JSO 集成- 编写一个JSNI函数,该函数返回已解析的对象并将其转换为您的JSO - 理论上它应该可以工作;)(这就是GWT内部使用JSO的内容,至少从我的理解)

至于在JSON中访问列表,有适当的类:( JsArray通用,用于其他JSO的列表)JsArrayString,等等.如果你看一下它们的实现,它们只是围绕本机JS数组的JSNI包装器,所以它们非常快(但由于某种原因有限).


编辑回应蒂姆的评论:

在处理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 + ')');
    }-*/;
}
Run Code Online (Sandbox Code Playgroud)

然后你写下你的实际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());
    }
}
Run Code Online (Sandbox Code Playgroud)

最后在你的代码中:

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

你的JSON看起来像这样(由JSONLint提供,一个很棒的JSON验证器):

{
    "item": [
        {
            "Id": "1",
            "Name": "Bob"
        },
        {
            "Id": "2",
            "Name": "John"
        },
        {
            "Id": "3",
            "Name": "Bill"
        }
    ]
}
Run Code Online (Sandbox Code Playgroud)

所以,我写了一个描述该列表项目的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;
    }-*/;
}
Run Code Online (Sandbox Code Playgroud)

然后,在你的代码中,你调用TestResponse.getTestList(someJsonString)并使用JsArray你得到的东西(TestResponse它包含的s是自动创建的).很酷,嗯?;)一开始可能有点令人困惑,但请相信我,一旦你开始使用它就会有意义,它比通过> _> 解析容易得多JSONParser