我正在处理一种情况,我需要反序列化多态类。
Class Pen{
String name;
List<Animal> animals;
}
//Animal can be an interface or parent class: I am flexible
Class Animal{
AnimalType type;//enum
int legs;
}
enum AnimalType{
dog,cat,pig,chicken;
}
Class AnimalDog extends Animal{
//…
}
Class AnimalCat extends Animal{
//…
}
Class AnimalPig extends Animal{
//…
}
然后我用
创建我的 Gson 实例public static Gson instanceUpperCamelCaseWithTypeAdapterFactory() {
if (null == sGsonUpperCamelCase) {
final RuntimeTypeAdapterFactory<Animal> typeFactory = RuntimeTypeAdapterFactory
.of(Animal.class, “type")
.registerSubtype(AnimalDog.class, “dog”)
.registerSubtype(AnimalCat.class, “cat”)
.registerSubtype(AnimalPig.class, “pig”);
sGsonUpperCamelCase = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
.registerTypeAdapterFactory(typeFactory).create();
}//the naming policy is because server sends me upper case fields whereas Java fields are lowercase.
return sGsonUpperCamelCase;
}
要从包含动物列表的 json 中获取动物,我会这样做
List<Animal> animals = gson.fromJson(json, new TypeToken<List<Animal>>() {}.getType());
我对Gson完全是个新手。完全地。那么,在不让我太困惑的情况下,我该如何解决这个问题呢?
错误追踪:
com.google.gson.JsonParseException: cannot deserialize class com.company.appname.data.model.Animal because it does not define a field named type
com.company.appname.utils.RuntimeTypeAdapterFactory$1.read(RuntimeTypeAdapterFactory.java:204)
com.google.gson.TypeAdapter$1.read(TypeAdapter.java:199)
com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:40)
com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:82)
com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:61)
com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:117)
com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:217)
com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:40)
com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:82)
com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:61)
com.google.gson.Gson.fromJson(Gson.java:861)
com.google.gson.Gson.fromJson(Gson.java:826)
com.google.gson.Gson.fromJson(Gson.java:775)
我通过在线验证器运行json,没有问题。它有许多项目。这里我展示两个。
{“Animals”:[{
“id":9,
“type”:”dog”,
“name”:”maximus”
},
{
“id":10,
“type”:”cat”,
“name”:”meowy”,
“yarns”:5,
“nice”:true
}]}
RuntimeTypeAdapterFactory.class 行号 -> 203
需要更换
JsonElement labelJsonElement = jsonElement.getAsJsonObject().remove(typeFieldName);
与
JsonElement labelJsonElement = jsonElement.getAsJsonObject().get(typeFieldName);
如果有人偶然发现这个老问题:-)
您可以在中设置maintainType = true
RuntimeTypeAdapterFactory.of(Animal.class, “type", true)
希望这对某人有帮助:-)
我在 RuntimeTypeAdapterFactory 中发现了错误(第 185 行,方法 create()),并解决了这个问题,需要替换
if (type.getRawType() != baseType)
与
if (null == type || !baseType.isAssignableFrom(type.getRawType()))
然后 RuntimeTypeAdapterFactory 按预期工作良好。
请参阅链接已注册问题以及建议的修复