我正在尝试解析来自gwt 2.0应用程序中的流的JSON。
最好的方法是什么?我应该使用javascriptobject吗? JSonParser?我迷失了我在网上创建的东西,因为从来没有gwt版本。
String text = "{\"item\":[{\"Id\":\"1\",\"Name\":\"Bob\"},{\"Id\":\"2\",\"Name\":\"John\"},{\"Id\":\"3\",\"Name\":\"Bill\"}]}";
如何玩我的物品清单?
提前感谢您提供任何帮助
答案 0 :(得分:33)
答案取决于您对JSON的信任程度:)当然,它可能来自您的应用程序,但如果插入一些不受信任的用户输入,您将面临可能的安全漏洞。
所以:
eval()
函数,这意味着(至少)两件事:JSON解析将非常快(它使用浏览器本机代码)并且可能不安全。 Google了解有关JSON相关安全问题的更多信息。当您调用JSONParser
方法时,parseLenient(String jsonString)
也可以通过eval()
解析JSON,但它肯定不如JSO那么有吸引力。JSONParser
使用JSONParser.parseStrict(String jsonString)
(在GWT> = 2.1中提供) - 您必须以这种方式编写更多代码,但您可以确定输入已正确处理。您还可以考虑将“官方”JSON parser from json.org与JSO集成 - 编写一个JSNI函数,该函数返回已解析的对象并将其强制转换为JSO - 理论上它应该工作;)(这就是GWT内部与JSO的关系,至少从我理解的内容开始)至于访问JSON中的列表,有适当的类:JsArray
(通用,用于其他JSO列表),JsArrayString
等。如果你看一下它们的实现,它们只是JSNI包装了本机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
(其中包含的TestResponse
是自动创建的)。很酷,嗯? ;)一开始可能有点令人困惑,但请相信我,一旦你开始使用它就会有意义,并且比通过JSONParser
&gt; _&gt;解析更容易