Java Gson序列化接口/抽象类
如果我使用接口或抽象类注册Java Gson序列化接口/抽象类,java,gson,serialization,Java,Gson,Serialization,如果我使用接口或抽象类注册JsonSerializer,如: GsonBuilder builder = new GsonBuilder() .registerTypeAdapter(MyInterface.class, new MySerializer()); Gson gson = builder.create(); MyInterface i = new MyConcreteClass(); String json = gson.toJson(i); // <--- Ser
JsonSerializer
,如:
GsonBuilder builder = new GsonBuilder()
.registerTypeAdapter(MyInterface.class, new MySerializer());
Gson gson = builder.create();
MyInterface i = new MyConcreteClass();
String json = gson.toJson(i); // <--- Serializer is not invoked
将调用序列化程序
对我来说,这是一种前后矛盾的行为。它在成员变量上的工作方式是查找声明的类型而不是实际的类型,但是它在“根”对象上的工作方式是不同的
这是错误/缺陷还是预期行为?如果这是预期的,有什么原因吗?这是预期的行为。Gson有一个要使用的默认
TypeAdapterFactory
对象列表。你可以在地图上看到它们
有用于字符串
、数字
、映射
、集合
的适配器。。。最后一个很重要,在没有适配器可以处理类型时使用:它是reflectTypeAdapter
。这个函数通过反射检索要序列化的对象的所有字段,并搜索适当的适配器来序列化字段的值
因此,当Gson必须序列化一个对象时,它首先尝试使用对象的实际类型来查找适配器。如果找到的适配器不是ReflectTypeAdapter
,它将使用它。否则,它将搜索声明性类型的适配器,如果它不是reflectTypeAdapter
,则使用它。否则,它会在对象上使用ReflectTypeAdapter
(您可以查看类的源代码,以了解有关此mecanism的更多详细信息)。这就是属性的行为MyInterface i
当您这样做时:
MyInterface i = new MyConcreteClass();
String json = gson.toJson(i);
Gson尝试为类型MyConcreteClass
查找适配器,并找到ReflectTypeAdapter
。因此,现在它应该搜索声明类型的适配器。但是它无法知道声明类型,因为没有对象引用它,这是根对象。您知道在代码中要使用类型MyInterface
,但Gson没有此信息,只有对象实例。您可能认为Gson可以看到对象实现了MyInterface
,但这不是它的工作方式(如果对象实现了两个接口怎么办?)
因此,有两种方法可以解决您的问题:
1) 调用Gson.toJson
时,可以为根对象指定声明类型:
2) 注册适配器时,可以指示此适配器适用于所有子类:
希望有帮助谢谢你的回答。尽管如此,由于Java的局限性,我认为这是一个预期的缺陷。当我使用registerTypeHierarchyAdapter时,当serialize方法执行result.add(“properties”,context.serialize(src,src.getClass())时,我陷入了一个连续循环中。我尝试了您的第一个解决方案,它给出了空的json{}
MyInterface i = new MyConcreteClass();
String json = gson.toJson(i);
String json = gson.toJson(i, MyInterface.class);
GsonBuilder builder = new GsonBuilder()
.registerTypeHierarchyAdapter(MyInterface.class, new MySerializer());