RuntimeTypeAdapterFactory 说“类型”未定义

Nou*_*vay 5 java android gson

我正在处理一种情况,我需要反序列化多态类。

\n\n
Class Pen{\n  String name;\n  List<Animal> animals;\n}\n\n//Animal can be an interface or parent class: I am flexible\n\nClass Animal{\n  AnimalType type;//enum\n  int legs;\n}\n\nenum AnimalType{\n  dog,cat,pig,chicken;\n}\n\nClass AnimalDog extends Animal{\n  //\xe2\x80\xa6\n}\n\nClass AnimalCat extends Animal{\n  //\xe2\x80\xa6\n}\n\n\nClass AnimalPig extends Animal{\n  //\xe2\x80\xa6\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

然后我创建我的 Gson 实例

\n\n
public static Gson instanceUpperCamelCaseWithTypeAdapterFactory() {\n    if (null == sGsonUpperCamelCase) {\n        final RuntimeTypeAdapterFactory<Animal> typeFactory = RuntimeTypeAdapterFactory\n                .of(Animal.class, \xe2\x80\x9ctype")\n                .registerSubtype(AnimalDog.class, \xe2\x80\x9cdog\xe2\x80\x9d)\n                .registerSubtype(AnimalCat.class, \xe2\x80\x9ccat\xe2\x80\x9d)\n                .registerSubtype(AnimalPig.class, \xe2\x80\x9cpig\xe2\x80\x9d);\n\n        sGsonUpperCamelCase = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)\n                .registerTypeAdapterFactory(typeFactory).create();\n    }//the naming policy is because server sends me upper case fields whereas Java fields are lowercase.\n    return sGsonUpperCamelCase;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

为了从包含动物列表的 json 中获取动物,我这样做

\n\n
List<Animal> animals = gson.fromJson(json, new TypeToken<List<Animal>>() {}.getType());\n
Run Code Online (Sandbox Code Playgroud)\n\n

我对Gson完全是个新手。完全地。那么,在不让我太困惑的情况下,我该如何解决这个问题呢?

\n\n

错误跟踪:

\n\n
com.google.gson.JsonParseException: cannot deserialize class com.company.appname.data.model.Animal because it does not define a field named type\ncom.company.appname.utils.RuntimeTypeAdapterFactory$1.read(RuntimeTypeAdapterFactory.java:204)\ncom.google.gson.TypeAdapter$1.read(TypeAdapter.java:199)\ncom.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:40)\ncom.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:82)\ncom.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:61)\ncom.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:117)\ncom.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:217)\ncom.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:40)\ncom.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:82)\ncom.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:61)\ncom.google.gson.Gson.fromJson(Gson.java:861)\ncom.google.gson.Gson.fromJson(Gson.java:826)\ncom.google.gson.Gson.fromJson(Gson.java:775)\n
Run Code Online (Sandbox Code Playgroud)\n\n

我通过在线验证器运行json,没有问题。它有许多项目。这里我展示两个。

\n\n
{\xe2\x80\x9cAnimals\xe2\x80\x9d:[{  \n           \xe2\x80\x9cid":9,\n           \xe2\x80\x9ctype\xe2\x80\x9d:\xe2\x80\x9ddog\xe2\x80\x9d,\n           \xe2\x80\x9cname\xe2\x80\x9d:\xe2\x80\x9dmaximus\xe2\x80\x9d\n        },\n        {  \n           \xe2\x80\x9cid":10,\n           \xe2\x80\x9ctype\xe2\x80\x9d:\xe2\x80\x9dcat\xe2\x80\x9d,\n           \xe2\x80\x9cname\xe2\x80\x9d:\xe2\x80\x9dmeowy\xe2\x80\x9d,\n           \xe2\x80\x9cyarns\xe2\x80\x9d:5,\n           \xe2\x80\x9cnice\xe2\x80\x9d:true\n        }]}\n
Run Code Online (Sandbox Code Playgroud)\n

小智 5

RuntimeTypeAdapterFactory.class 行号 -> 203

需要更换

JsonElement labelJsonElement = jsonElement.getAsJsonObject().remove(typeFieldName);
Run Code Online (Sandbox Code Playgroud)

JsonElement labelJsonElement = jsonElement.getAsJsonObject().get(typeFieldName);
Run Code Online (Sandbox Code Playgroud)


ult*_*aon -1

我在 RuntimeTypeAdapterFactory 中发现了错误(第 185 行,方法 create()),并解决了此问题,需要替换

if (type.getRawType() != baseType)
Run Code Online (Sandbox Code Playgroud)

if (null == type || !baseType.isAssignableFrom(type.getRawType()))
Run Code Online (Sandbox Code Playgroud)

然后 RuntimeTypeAdapterFactory 按预期工作。

请参阅链接已注册问题以及建议的修复