java - Gson序列化接口(interface)/抽象类

标签 java gson serialization

如果我使用接口(interface)抽象类注册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.toJson()中根本没有调用序列化器。

但是,如果我有一个包含 MyInterface 的类:

public class MyAnotherClass {
    MyInterface i;
    // ...
}

MyAnotherClass c = new MyAnotherClass()
String json = gson.toJson(c); // <--- Serializer is invoked

调用序列化器。

对我来说,这是一种不一致的行为。它对成员变量的工作方式是查找声明类型而不是实际类型,但它对“根”对象的工作方式不同。

这是错误/缺陷还是预期行为?如果这是预期的,背后有什么原因吗?

最佳答案

这是预期的行为。 Gson 有一个要使用的默认 TypeAdapterFactory 对象列表。您可以在 source of the Gson class 中看到它们.

StringNumberMapCollection的适配器...最后一个很重要当没有适配器可以处理某种类型时使用:它是ReflectiveTypeAdapter。该方法通过反射检索要序列化的对象的所有字段,并搜索适当的适配器来序列化字段的值。

因此,当 Gson 必须序列化一个对象时,它首先尝试使用该对象的实际类型来查找适配器。如果找到的适配器不是 ReflectiveTypeAdapter,则会使用它。否则,它会搜索具有声明性类型的适配器,如果它不是 ReflectiveTypeAdapter,则使用它。否则,它会在对象上使用 ReflectiveTypeAdapter (您可以查看类的源代码 TypeAdapterRuntimeTypeWrapper 以了解有关此机制的更多详细信息)。这就是您的属性 MyInterface i 的行为。

当你这样做时:

MyInterface i = new MyConcreteClass();
String json = gson.toJson(i);

Gson 尝试查找 MyConcreteClass 类型的适配器,它找到了 ReflectiveTypeAdapter。所以现在它应该搜索声明类型的适配器。但它无法知道声明类型,因为没有对象引用它,这是根对象。您知道在代码中要使用 MyInterface 类型,但 Gson 没有此信息,只有对象实例。您可能认为 Gson 可以看到该对象实现了 MyInterface,但这不是它的工作方式(如果该对象实现了两个接口(interface)该怎么办?)

所以,你有两种方法来解决你的问题:

1) 当你调用Gson.toJson时,你可以给出根对象的声明类型:Gson#toJson(Object, Type)

String json = gson.toJson(i, MyInterface.class);

2) 当您注册适配器时,您可以指示此适配器适用于所有子类:GsonBuilder#registerTypeHierarchyTree

GsonBuilder builder = new GsonBuilder()
    .registerTypeHierarchyAdapter(MyInterface.class, new MySerializer());

希望对你有帮助

关于java - Gson序列化接口(interface)/抽象类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28362229/

相关文章:

java - tomcat 如何为语言环境请求提供 Http,为远程请求提供 https

java - 预期为 BEGIN_ARRAY,但使用 GSON 时为 BEGIN_OBJECT

java - GSON 没有正确解析嵌套的 JSON 对象

wcf - 为什么我不能在我的 WCF 类中使用 KnownType 属性?

Java 序列化产生 NotSerializedException(原因未知)

java - 如何在 Java 中添加新的替代构造函数?

java - 通过Java程序连接Oracle

java - 从 InputStream 读取

java - 使用 GSON 和 lambda 过滤 JSON

c# - .NET 序列化 XmlNode 问题