gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-02 18:18:21 31 4
gpt4 key购买 nike

如果我使用接口(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/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com