Rya*_*n R 16 android json retrofit
我遇到的问题是我正在解析的API为大小为1的ARRAY返回一个OBJECT.
例如,有时API会响应:
{
"monument": [
{
"key": 4152,
"name": "MTS - Corporate Head Office",
"categories": {},
"address": {}
},
{
"key": 4151,
"name": "Canadian Transportation Agency",
"categories": {},
"address": {}
},
{
"key": 4153,
"name": "Bank of Montreal Building",
"categories": {},
"address": {}
}
],
}
Run Code Online (Sandbox Code Playgroud)
但是,如果monument数组只有一个项目,它就变成了一个OBJECT(注意缺少[]括号),如下所示:
{
"monument": {
"key": 4152,
"name": "MTS - Corporate Head Office",
"categories": {},
"address": {}
}
}
Run Code Online (Sandbox Code Playgroud)
如果我像这样定义我的模型,只返回一个项目时会出错:
public class Locations {
public List<Monument> monument;
}
Run Code Online (Sandbox Code Playgroud)
如果只返回一个项目,我会收到以下错误:
Expected BEGIN_OBJECT but was BEGIN_ARRAY ...
Run Code Online (Sandbox Code Playgroud)
如果我像这样定义我的模型:
public class Locations {
public Monument monument;
}
Run Code Online (Sandbox Code Playgroud)
并且API返回ARRAY我得到了相反的错误
Expected BEGIN_ARRAY but was BEGIN_OBJECT ...
Run Code Online (Sandbox Code Playgroud)
我无法在模型中定义多个具有相同名称的项目.我该如何处理这个案子?
注意:我无法对API进行更改.
pak*_*ldt 12
诀窍是为你的班级编写自己的Gson反序列化器Locations.这将检查纪念碑元素是对象还是数组.像这样:
public class LocationsDeserializer implements JsonDeserializer<Locations> {
@Override
public Locations deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
JsonElement monumentElement = json.getAsJsonObject().get("monument");
if (monumentElement.isJsonArray()) {
return new Locations((Monument[]) context.deserialize(monumentElement.getAsJsonArray(), Monument[].class));
} else if (monumentElement.isJsonObject()) {
return new Locations((Monument) context.deserialize(monumentElement.getAsJsonObject(), Monument.class));
} else {
throw new JsonParseException("Unsupported type of monument element");
}
}
}
Run Code Online (Sandbox Code Playgroud)
为方便起见,在您的Locations类中添加一个vararg构造函数:
public class Locations {
public List<Monument> monuments;
public Locations(Monument ... ms) {
monuments = Arrays.asList(ms);
}
}
Run Code Online (Sandbox Code Playgroud)
你的纪念碑课程保持不变.就像是:
public class Monument {
public int key;
public String name;
// public Categories categories;
// public Address address;
}
Run Code Online (Sandbox Code Playgroud)
最后,创建自己的Gson对象并将其传递给改造RestAdapter.
Gson gson = new GsonBuilder().registerTypeAdapter(Locations.class, new LocationsDeserializer()).create();
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint(baseUrl)
.setConverter(new GsonConverter(gson))
.build();
Run Code Online (Sandbox Code Playgroud)
pak*_*ldt 12
作为我之前的答案的补充,这是一个使用a的解决方案TypeAdapter.
public class LocationsTypeAdapter extends TypeAdapter<Locations> {
private Gson gson = new Gson();
@Override
public void write(JsonWriter jsonWriter, Locations locations) throws IOException {
gson.toJson(locations, Locations.class, jsonWriter);
}
@Override
public Locations read(JsonReader jsonReader) throws IOException {
Locations locations;
jsonReader.beginObject();
jsonReader.nextName();
if (jsonReader.peek() == JsonToken.BEGIN_ARRAY) {
locations = new Locations((Monument[]) gson.fromJson(jsonReader, Monument[].class));
} else if(jsonReader.peek() == JsonToken.BEGIN_OBJECT) {
locations = new Locations((Monument) gson.fromJson(jsonReader, Monument.class));
} else {
throw new JsonParseException("Unexpected token " + jsonReader.peek());
}
jsonReader.endObject();
return locations;
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6340 次 |
| 最近记录: |