我尝试使用具有以下返回值的API:
{
"data":{
"id":"12345",
"name":"Some Name",
"regions":[
"r987",
"r654"
]
}
}
区域属性是List<String>
,只有区域ID
但是我可以要求同一个请求检索完整的区域对象,所以json改为:
{
"data":{
"id":"12345",
"name":"Some Name",
"regions":{
"data":[
{
"id":"r987",
"name":"region 1"
},
{
"id":"r654",
"name":"region 2"
}
]
}
}
}
我想创建一个适配器来始终翻译Id列表以返回包含完整对象的列表,例如
class RegionListAdapter implements JsonDeserializer<List<Region>> {
@Override
public List<Region> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext jsc) throws JsonParseException {
List<Region> result = new ArrayList<>();
if (json.isJsonObject()) {
JsonObject envelope = json.getAsJsonObject();
JsonArray data = envelope.getAsJsonArray("data");
result = jsc.deserialize(data, typeOfT);
} else {
JsonArray idArray = json.getAsJsonArray();
for(JsonElement e : idArray){
String regionId = e.getAsString();
Region region = new Region(regionId);
result.add(region);
}
}
return result;
}
}
并且一切正常,仅接收ID或完整对象...
问题是,我有其他属性以相同的方式工作。有没有办法让这个适配器一般工作或以不同的方式工作?或者我需要为每个对象创建一个适配器?
答案 0 :(得分:0)
制作此泛型的难点在于您需要创建列表中对象类型的新实例。如果所有对象都将使用名为id
的字段作为列表版本中的内容,我们可以使用它来创建新实例。最简单的黑客攻击如下所示,我们将字符串作为id
字段填充到新的JsonObject
中,然后使用Gson构造新对象。
class IdListAdapter<T> implements JsonDeserializer<List<T>> {
@Override
public List<T> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext jsc) throws JsonParseException {
if (json.isJsonObject()) {
JsonObject envelope = json.getAsJsonObject();
JsonArray data = envelope.getAsJsonArray("data");
return jsc.deserialize(data, typeOfT);
} else {
JsonArray idArray = json.getAsJsonArray();
List<T> result = new ArrayList<T>(idArray.size());
for (JsonElement id : idArray) {
if (typeOfT instanceof ParameterizedType) {
Type parameterType = ((ParameterizedType) typeOfT).getActualTypeArguments()[0];
JsonObject obj = new JsonObject();
obj.add("id", id);
T element = jsc.deserialize(obj, parameterType);
result.add(element);
}
}
return result;
}
}
}