Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Gson序列化接口/抽象类_Java_Gson_Serialization - Fatal编程技术网

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());