我们正在使用Retrofit库v1.9.0来使用REST调用从我们的服务器中检索Web服务。
问题是,我必须指定webservice中每个对象的返回类型,否则抛出异常。这是一个例子:
serviceTest.testWebservice(new Callback<MessageFromWebservice>() {
@Override
public void success(MessageFromWebservice message, Response response) {
Log.i(TAG, "Test returned : " + message.toString());
}
@Override
public void failure(RetrofitError retrofitError) {
Log.e(TAG, "Test error : " + retrofitError.toString());
}
});
我的回调是
class MessageFromWebservice{
private List<Product> products;
}
所以,我的Android应用程序必须只检索一些产品:JSON必须
"{products: [
{label="Product1", price="12"},
{label="Product2", price="21"}
]}"
现在,我的服务器只能向我发送一个产品,结果JSON将是一个对象产品而不是产品阵列。
"{products:{label="Product1", price="12"}}"
每当发生这种情况时,Retrofit会抛出异常,应用程序崩溃。
我不明白为什么Retrofit无法处理来自服务器的未知返回类型(同一变量中的单个Object或Array)。
如果我的Class想要一个List,并且Web服务返回一个Product,则错误如下所示。
retrofit.RetrofitError: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 14 path $.products
有这个解决方案: How to handle Dynamic JSON in Retrofit?
但似乎太复杂了,不能包含在Retrofit库中......
答案 0 :(得分:0)
您可以为您的Gson转换器使用自定义deserializer。基本思想是在将响应转换为Json树之后但在将其转换为对象之前拦截反序列化。在反序列化器中,检查products
字段以查看它是数组还是单个对象,并根据需要进行反序列化。这是一个如何在上面找到你的对象的草图。
public class MessageSerializer implements JsonDeserializer<MessageFromWebservice> {
@Override
public MessageFromWebservice deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
MessageFromWebservice message = new MessageFromWebservice();
if(json.isJsonObject()) {
JsonObject jsonObject = json.getAsJsonObject();
if(jsonObject.has("products")) {
JsonElement products = jsonObject.get("products");
if(products.isJsonArray()) {
Type productListType = new TypeToken<List<Product>>(){}.getType();
message.products = context.deserialize(products, productListType);
} else {
message.products = new ArrayList<Product>(1);
Product product = context.deserialize(products, Product.class);
message.products.add(product);
}
}
return message;
} else {
// top level is supposed to be an object
throw new IllegalStateException();
}
}
}
然后你可以创建一个自定义的Gson实例并注册上面的适配器 -
Gson gson = new GsonBuilder()
.registerTypeAdapter(MessageFromWebservice.class, new MessageSerializer())
.create();
并在setConverter(new GsonConverter(gson))
构建器中添加对RestAdapter
的调用。喜欢 -
RestAdapter restAdapter = new RestAdapter.Builder()
.setConverter(new GsonConverter(gson))
//... other options
.build();