基于gson的java多态性
我在用Gson反序列化json字符串时遇到问题。 我收到一系列命令。该命令可以是启动、停止或其他类型的命令。当然我有多态性,启动/停止命令继承自命令
如何使用gson将其序列化回正确的命令对象
似乎我只得到基类型,即声明的类型,而不是运行时类型
你可以在下面搜索框中键入要查询的问题!
我在用Gson反序列化json字符串时遇到问题。 我收到一系列命令。该命令可以是启动、停止或其他类型的命令。当然我有多态性,启动/停止命令继承自命令
如何使用gson将其序列化回正确的命令对象
似乎我只得到基类型,即声明的类型,而不是运行时类型
# 1 楼答案
GSON在这里有一个非常好的测试用例,展示了如何定义和注册类型层次结构适配器
http://code.google.com/p/google-gson/source/browse/trunk/gson/src/test/java/com/google/gson/functional/TypeHierarchyAdapterTest.java?r=739
要使用它来实现这一点:
适配器的Serialize方法可以是级联的if-else检查它正在序列化的类型
反序列化有点老套。在单元测试示例中,它检查是否存在指示灯属性,以决定反序列化到哪个类。如果可以更改要序列化的对象的源,则可以为每个实例添加一个“classType”属性,该属性包含实例类名称的FQN。但这是非常不面向对象的
# 2 楼答案
这有点晚了,但我今天不得不做同样的事情。因此,根据我的研究,在使用gson-2.0时,你真的不想使用registerTypeHierarchyAdapter方法,而是更普通的registerTypeAdapter。当然,您不需要为派生类执行instanceofs或编写适配器:只需为基类或接口编写一个适配器,当然前提是您对派生类的默认序列化感到满意。无论如何,下面是代码(已删除包和导入)(也可在github中获得):
基类(在我的例子中是接口):
两个派生类,Cat:
还有狗:
IAnimalAdapter:
还有测试课:
运行Test::main时,您会得到以下输出:
实际上,我也使用了registerTypeHierarchyAdapter方法完成了上述操作,但这似乎需要实现自定义DogAdapter和CatAdapter序列化器/反序列化器类,这是在任何时候向Dog或Cat添加另一个字段时都很难维护的
# 3 楼答案
谷歌已经发布了自己的RuntimeTypeAdapterFactory来处理多态性,但不幸的是,它不是gson核心的一部分(您必须在项目中复制并粘贴该类)
例如:
Here我发布了一个完整的工作示例,使用了动物、狗和猫模型
我认为最好依靠这个适配器,而不是从头开始重新实现它
# 4 楼答案
马库斯·朱尼乌斯·布鲁特斯回答得很好(谢谢!)。为了扩展他的示例,您可以通过以下更改使他的适配器类通用,以适用于所有类型的对象(不仅仅是IAnimal):
在测试课上:
# 5 楼答案
很长时间过去了,但我在网上找不到真正好的解决方案。。 这里是@MarcusJuniusBrutus解决方案的一个小转折,它避免了无限递归
保留相同的反序列化程序,但删除序列化程序-
然后,在原始类中,添加一个带有
@SerializedName("CLASSNAME")
的字段。 现在的诀窍是在基类的构造函数中初始化它,因此将接口变成一个抽象类这里没有无限递归的原因是我们将实际的运行时类(即Dog而不是IAnimal)传递给
context.deserialize
。只要我们使用registerTypeAdapter
而不是registerTypeHierarchyAdapter
,这就不会调用我们的类型适配器# 6 楼答案
Gson目前有一个register a Type Hierarchy Adapter机制,据报道可以配置为简单的多态反序列化,但我不知道是怎么回事,因为类型层次结构适配器似乎只是一个组合的序列化器/反序列化器/实例创建者,实例创建的细节由编码器决定,不提供任何实际的多态类型注册
看起来Gson很快就会有
RuntimeTypeAdapter
来实现更简单的多态反序列化。有关更多信息,请参见http://code.google.com/p/google-gson/issues/detail?id=231如果无法使用新的
RuntimeTypeAdapter
,而您必须使用Gson,那么我认为您必须推出自己的解决方案,将自定义反序列化器注册为类型层次结构适配器或类型适配器。下面就是这样一个例子