我正在使用一个api(Phillips Hue),它将所有json响应包含在一个带有一个条目(内容)的数组中。
示例:
[{
"error": {
"type": 5,
"address": "/",
"description": "invalid/missing parameters in body"
}
}]
我经常编写由GSON解析的标准POJO来处理响应,但由于响应不是json对象,我对处理这个问题的最佳方法感到有些困惑。我真的不希望每个对象实际上都是一个我必须调用.get(0)的数组。
POJO的示例,如果它是JSON obj而未包装在数组中。
public class DeviceUserResponse {
private DeviceUser success;
private Error error;
public DeviceUser getSuccess() {
return success;
}
public Error getError() {
return error;
}
public static class Error {
private int type;
private String address;
private String description;
public int getType() {
return type;
}
public String getAddress() {
return address;
}
public String getDescription() {
return description;
}
@Override
public String toString() {
return "Type: " + this.type
+ " Address: " + this.address
+ " Description: " + this.description;
}
}
}
我现在必须做的事情:
ArrayList<DeviceUserResponse> response.get(0).getError();
有没有办法可以为每个响应删除这个数组,或者我只需要在我的POJO中执行.get(0)而不暴露它?
答案 0 :(得分:2)
我认为你要使用自定义反序列化来“剥离”数组。
这是一个可能的解决方案。
您的回复POJO的适配器:
public class DeviceUserResponseAdapter extends TypeAdapter<DeviceUserResponse> {
protected TypeAdapter<DeviceUserResponse> defaultAdapter;
public DeviceUserResponseAdapter(TypeAdapter<DeviceUserResponse> defaultAdapter) {
this.defaultAdapter = defaultAdapter;
}
@Override
public void write(JsonWriter out, DeviceUserResponse value) throws IOException {
defaultAdapter.write(out, value);
}
@Override
public DeviceUserResponse read(JsonReader in) throws IOException {
in.beginArray();
assert(in.hasNext());
DeviceUserResponse response = defaultAdapter.read(in);
in.endArray();
return response;
}
}
适配器的工厂:
public class DeviceUserResponseAdapterFactory implements TypeAdapterFactory {
@Override
@SuppressWarnings("unchecked")
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
if (type.getRawType()!=DeviceUserResponse.class) return null;
TypeAdapter<DeviceUserResponse> defaultAdapter = (TypeAdapter<DeviceUserResponse>) gson.getDelegateAdapter(this, type);
return (TypeAdapter<T>) new DeviceUserResponseAdapter(defaultAdapter);
}
}
然后你要注册并使用它:
DeviceUserResponseAdapterFactory adapterFactory = new DeviceUserResponseAdapterFactory();
GsonBuilder gsonBuilder = new GsonBuilder();
Gson gson = gsonBuilder.registerTypeAdapterFactory(adapterFactory).create();
DeviceUserResponse response = gson.fromJson(json, DeviceUserResponse.class);
System.out.println(response.getError());
如果您在其他复杂的JSON对象中包含DeviceUserResponse,则此解决方案将无效。在那种情况下,适配器将尝试查找数组,并将以错误终止。
另一种解决方案是将其解析为数组,然后在“通信”层中只获得第一个元素。这将保留GSon反序列化。
在评论中你要求更通用的解决方案,这里有一个: 适配器:
public class ResponseAdapter<T> extends TypeAdapter<T> {
protected TypeAdapter<T> defaultAdapter;
public ResponseAdapter(TypeAdapter<T> defaultAdapter) {
this.defaultAdapter = defaultAdapter;
}
@Override
public void write(JsonWriter out, T value) throws IOException {
defaultAdapter.write(out, value);
}
@Override
public T read(JsonReader in) throws IOException {
in.beginArray();
assert(in.hasNext());
T response = defaultAdapter.read(in);
in.endArray();
return response;
}
}
工厂:
public class ResponseAdapterFactory implements TypeAdapterFactory {
@Override
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
if ((type.getRawType().getSuperclass() != Response.class)) return null;
TypeAdapter<T> defaultAdapter = (TypeAdapter<T>) gson.getDelegateAdapter(this, type);
return (TypeAdapter<T>) new ResponseAdapter<T>(defaultAdapter);
}
}
其中Response.class是您所有服务响应继承的超类。 第一个解决方案建议仍然有效。