【问题标题】:Parse json with gwt 2.0使用 gwt 2.0 解析 json
【发布时间】:2010-08-10 12:54:34
【问题描述】:

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

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

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

如何使用我的项目列表?

提前感谢您的帮助

【问题讨论】:

    标签: json gwt


    【解决方案1】:

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

    所以:

    • 对于来自可信来源的 JSON,我使用 JavaScript Overlay Types。他们使 JSON 与 GWT 无缝集成,我肯定会推荐这种方法。然而,在内部,这调用了eval() 函数,这意味着(至少)两件事:JSON 解析将非常快(它使用浏览器的本机代码)并且可能不安全。谷歌了解更多关于 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(通用,用于其他 JSO 的列表)、JsArrayString 等。如果您查看它们的实现,它们只是围绕原生 JS 数组,因此它们非常快(但由于某种原因受到限制)。


    编辑以回应 Tim 的评论:

    在处理 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(它包含的TestResponses 是自动创建的)。酷,嗯? ;) 一开始可能有点令人困惑,但相信我,一旦你开始使用它就会变得有意义,而且它比通过 JSONParser 解析要容易得多 >_>

    【讨论】:

    • 谢谢你的帮助,我准备使用js覆盖类型。但是我将如何翻译我的 json 文本来获得客户?在示例中,他使用:$wnd.jsonData[0];就我而言,我有一个字符串(来自 RequestBuilder)
    • 完美运行,谢谢。我错过了评估功能。最好的问候
    • 为什么在 eval 中的字符串周围使用大括号?在此代码中:return eval('(' + responseString + ')');
    • @Davor:问得好! :) 我不是 JavaScript 专家,我可能从某个地方复制了该部分,但 json.org 给出了这样的解释:The text must be wrapped in parens to avoid tripping on an ambiguity in JavaScript's syntax。相关 SO 问题:onetwo
    • 感谢您的快速响应!是的,没有它们对我来说是行不通的,所以我想知道到底发生了什么......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-25
    • 1970-01-01
    • 1970-01-01
    • 2010-11-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多