我有一个可以处理多个JSON响应的模型。不过这是一个回应:
items: [
{
kind: "youtube#playlistItem",
etag: ""fpJ9onbY0Rl_LqYLG6rOCJ9h9N8/jqbcTLu8tYm8b1FXGO14gNZrFG4"",
id: "PLUQ7I1jJqKB4lJarGcpWsP62l7iC06IkE2LDE0BxLe18",
与此相冲突(请注意具有不同类型的相同id
字段。上述id
为String
,另一个为Class
):
items: [
{
kind: "youtube#searchResult",
etag: ""fpJ9onbY0Rl_LqYLG6rOCJ9h9N8/hDIU49vmD5aPhKUN5Yz9gtljG9A"",
id: {
kind: "youtube#playlist",
playlistId: "PLh6xqIvLQJSf3ynKVEc1axUb1dQwvGWfO"
},
我想使用单个模型类阅读id
字段。
这是我的模型Response
类:
public class Response {
private ArrayList<Item> items = new ArrayList<Item>();
这是我的模型Item
类:
public class Item {
private Id id;
//nested class inside Item
public class Id
{
private String id;
private String kind;
private String playlistId;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getKind() {
return kind;
}
public void setKind(String kind) {
this.kind = kind;
}
public String getPlaylistId() {
return playlistId;
}
public void setPlaylistId(String playlistId) {
this.playlistId = playlistId;
}
}
请注意,Id
类位于Item
类中。
这就是我使用registerTypeAdapter
的方式:
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Response.class,
new JsonDeserializer<Item.Id>() {
@Override
public Item.Id deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
Item.Id result = new Item().new Id();
if(jsonElement.isJsonPrimitive() == false)
{
result.setKind(jsonElement.getAsJsonObject().get("kind").getAsString());
result.setPlaylistId(jsonElement.getAsJsonObject().get("playlistId").getAsString());
//return new Item.Id(jsonElement.getAsJsonObject().get("kind").getAsString(), jsonElement.getAsJsonObject().get("playlistId").getAsString());
return result;
}
else
{
result.setId(jsonElement.getAsString());
//return new Item.Id(jsonElement.getAsString());
return result;
}
}
});
Gson gson = gsonBuilder.create();
Response result = Response.success(
gson.fromJson(json, gsonClass),
HttpHeaderParser.parseCacheHeaders(response));
但是上面的代码会在此行中抛出java.lang.NullPointerException
:
if(jsonElement.isJsonPrimitive() == false)
我该怎么办?
这是使用registerTypeAdapter
的正确方法吗?
感谢您的时间
答案 0 :(得分:2)
您的主要问题似乎是您正在为Response
类注册类型适配器,但是您正在提供处理JsonDeserializer
类的Item.Id
。您可以将完整Response
反序列化,也可以将自己限制为Item
甚至Item.Id
。
直接反序列化Item.Id
(如您的问题中所述)的另一个问题是它是一个非 - 静态内部类,它需要一个实例要实例化的父类(与new Item().new Id()
一样)。如果你想保留它,我认为你必须手动反序列化整个Item
,坦率地说,我认为没有任何理由不使Item.Id
静态,因为它会简化问题。 / p>
这是我的静态版Item.Id
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(Item.Id.class, new JsonDeserializer<Item.Id>() {
@Override
public Item.Id deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
Item.Id id = new Item.Id();
if (!json.isJsonPrimitive()) {
JsonObject jsonObject = json.getAsJsonObject();
id.setKind(jsonObject.get("kind").getAsString());
id.setPlaylistId(jsonObject.get("playlistId").getAsString());
} else {
id.setId(json.getAsString());
}
return id;
}
});
一些似乎对我有用的测试片段:
Gson gson = builder.create();
Response response = gson.fromJson("{\n" +
" \"items\": [\n" +
" {\n" +
" \"kind\": \"youtube#playlistItem\",\n" +
" \"etag\": \"fpJ9onbY0Rl_LqYLG6rOCJ9h9N8/jqbcTLu8tYm8b1FXGO14gNZrFG4\",\n" +
" \"id\": \"PLUQ7I1jJqKB4lJarGcpWsP62l7iC06IkE2LDE0BxLe18\"\n" +
" }\n" +
" ]\n" +
"}", Response.class);
Response response2 = gson.fromJson("{\n" +
" \"items\": [\n" +
" {\n" +
" \"kind\": \"youtube#searchResult\",\n" +
" \"etag\": \"fpJ9onbY0Rl_LqYLG6rOCJ9h9N8/hDIU49vmD5aPhKUN5Yz9gtljG9A\",\n" +
" \"id\": {\n" +
" \"kind\": \"youtube#playlist\",\n" +
" \"playlistId\": \"PLh6xqIvLQJSf3ynKVEc1axUb1dQwvGWfO\"\n" +
" }\n" +
" }\n" +
" ]\n" +
"}", Response.class);
如果您想保持Item.Id
非静态,我认为您需要为Item
编写反序列化器。还要记住,json元素可以不存在,但解析器应该仍然能够处理它。
答案 1 :(得分:1)
我很久以前就遇到了同样的问题,但我当时正在使用Json.Net,但是json概念(几乎)是相同的,所以我希望我能成功帮助。
我想它可能不起作用,但为什么不尝试注册Item类?我的意思是没有&#39; Item.Id&#39;因此,它的obious得到一个null。但是这个:gsonBuilder.registerTypeAdapter(Item.class,
可能会失败,因为你没有明确地解析Item类(但它可能有效,我从来没有在Gson中尝试过。但是在Json.Net中,类似的方法可以正常工作。)
那么,你怎么能解决这个问题呢?我懒得写一个游侠,但你可以查看here并阅读here的surt摘要摘要(搜索Using the registerTypeAdapter()
。
我希望我能帮忙。