我正在开发一个小应用程序并使用GWT来构建它。 我刚尝试向远程服务器发出请求,该服务器将以JSON的形式返回响应。 我尝试过使用叠加类型概念,但我无法使用它。我一直在改变代码,所以它与谷歌GWT教程留下的地方有点不同。
JavaScriptObject json;
public JavaScriptObject executeQuery(String query) {
String url = "http://api.domain.com?client_id=xxxx&query=";
RequestBuilder builder = new RequestBuilder(RequestBuilder.GET,
URL.encode(url + query));
try {
@SuppressWarnings("unused")
Request request = builder.sendRequest(null, new RequestCallback() {
public void onError(Request request, Throwable exception) {
// violation, etc.)
}
public void onResponseReceived(Request request,
Response response) {
if (200 == response.getStatusCode()) {
// Process the response in response.getText()
json =parseJson(response.getText());
} else {
}
}
});
} catch (RequestException e) {
// Couldn't connect to server
}
return json;
}
public static native JavaScriptObject parseJson(String jsonStr) /*-{
return eval(jsonStr );
;
}-*/;
在chrome的调试器中,我得到了umbrellaexception,无法看到堆栈跟踪,GWT调试器因NoSuchMethodError而崩溃......任何想法,指针?
答案 0 :(得分:13)
您可以查看GWT AutoBean framework。
AutoBean允许您从普通旧Java对象序列化和反序列化JSON字符串。
对我来说,这个框架变得至关重要:
您只需使用getter和setter定义接口:
// Declare any bean-like interface with matching getters and setters,
// no base type is necessary
interface Person {
Address getAddress();
String getName();
void setName(String name):
void setAddress(Address a);
}
interface Address {
String getZipcode();
void setZipcode(String zipCode);
}
稍后您可以使用工厂(See documentation)序列化或反序列化JSON字符串:
// (...)
String serializeToJson(Person person) {
// Retrieve the AutoBean controller
AutoBean<Person> bean = AutoBeanUtils.getAutoBean(person);
return AutoBeanCodex.encode(bean).getPayload();
}
Person deserializeFromJson(String json) {
AutoBean<Person> bean = AutoBeanCodex.decode(myFactory, Person.class, json);
return bean.as();
}
// (...)
Stack Overflow上的第一篇文章(!):我希望这有帮助:)
答案 1 :(得分:5)
JsonUtils#safeEval()
来评估JSON字符串,而不是直接调用eval()
。更重要的是,不要尝试使用RequestBuilder#sendRequest()
将异步调用的结果(如return
)传递给调用者 - 使用回调:
public void executeQuery(String query,
final AsyncCallback<JavaScriptObject> callback)
{
...
try {
builder.sendRequest(null, new RequestCallback() {
public void onError(Request request, Throwable caught) {
callback.onFailure(caught);
}
public void onResponseReceived(Request request, Response response) {
if (Response.SC_OK == response.getStatusCode()) {
try {
callback.onSuccess(JsonUtils.safeEval(response.getText()));
} catch (IllegalArgumentException iax) {
callback.onFailure(iax);
}
} else {
// Better to use a typed exception here to indicate the specific
// cause of the failure.
callback.onFailure(new Exception("Bad return code."));
}
}
});
} catch (RequestException e) {
callback.onFailure(e);
}
}
答案 2 :(得分:5)
通常,您描述的工作流程包含四个步骤:
听起来你已经让步骤1和2正常工作了。
JSONParser.parseStrict
会做得很好。您将收到一个JSONValue
对象。
这将允许您避免使用自定义本机方法,并且还将确保在解析JSON时它可以防止任意代码执行。如果您的JSON有效负载是可信的并且您想要原始速度,请使用
JSONParser.parseLenient
。在任何一种情况下,您都不需要编写自己的解析器方法。
假设你期待以下JSON:
{
"name": "Bob Jones",
"occupations": [
"Igloo renovations contractor",
"Cesium clock cleaner"
]
}
由于您知道JSON描述了一个对象,因此您可以告诉JSONValue
您希望获得JavaScriptObject
。
String jsonText = makeRequestAndGetJsonText(); // assume you've already made request
JSONValue jsonValue = JSONParser.parseStrict(jsonText);
JSONObject jsonObject = jsonValue.isObject(); // assert that this is an object
if (jsonObject == null) {
// uh oh, it wasn't an object after
// do error handling here
throw new RuntimeException("JSON payload did not describe an object");
}
现在您知道您的JSON描述了一个对象,您可以获取该对象并根据JavaScript类对其进行描述。假设你有这种叠加类型:
class Person {
String getName() /*-{
return this.name;
}-*/;
JsArray getOccupations() /*-{
return this.occupations;
}-*/;
}
您可以通过执行转换来使新的JavaScript对象符合此Java类:
Person person = jsonObject.getJavaScriptObject().cast();
String name = person.getName(); // name is "Bob Jones"
答案 3 :(得分:0)
使用eval
通常是危险的,并且如果服务器返回无效的JSON,可能会导致各种奇怪的行为(注意,如果您只是使用{JSON top元素是一个数组,则必须使用{ {1}}!)。所以我会让服务器返回一个非常简单的结果,如
eval(jsonStr)
并查看,如果错误仍然存在,或者您是否可以获得更好的堆栈跟踪。
注意:我认为服务器可以在与GWT主机页面相同的URL +端口+协议下访问(否则,由于同源策略,RequestBuilder无法正常工作。)
答案 4 :(得分:0)
您实际上不需要解析JSON,您可以使用本机JSNI对象(JavaScript Native Interface)。
这是我从最近的一个项目中提取的一个例子,它基本上与你正在做的事情相同:
public class Person extends JavaScriptObject{
// Overlay types always have protected, zero argument constructors.
protected Person(){}
// JSNI methods to get stock data
public final native String getName() /*-{ return this.name; }-*/;
public final native String getOccupation() /*-{ return this.occupation; }-*/;
// Non-JSNI methods below
}
然后像这样检索它:
/**
* Convert the string of JSON into JavaScript object.
*
*/
private final native JsArray<Person> asArrayOfPollData(String json) /*-{
return eval(json);
}-*/;
private void retrievePeopleList(){
errorMsgLabel.setVisible(false);
String url = JSON_URL;
url = URL.encode(url);
RequestBuilder builder = new RequestBuilder(RequestBuilder.POST, url);
try{
@SuppressWarnings("unused")
Request request = builder.sendRequest(null, new RequestCallback() {
@Override
public void onResponseReceived(Request req, Response resp) {
if(resp.getStatusCode() == 200){
JsArray<Person> jsonPeople = asArrayOfPeopleData(resp.getText());
populatePeopleTable(people);
}
else{
displayError("Couldn't retrieve JSON (" + resp.getStatusText() + ")");
}
}
@Override
public void onError(Request req, Throwable arg1) {
System.out.println("couldn't retrieve JSON");
displayError("Couldn't retrieve JSON");
}
});
} catch(RequestException e) {
System.out.println("couldn't retrieve JSON");
displayError("Couldn't retrieve JSON");
}
}
基本上,您将响应作为JSON对象数组进行转换。好东西。
此处有更多信息:http://code.google.com/webtoolkit/doc/latest/DevGuideCodingBasicsJSNI.html