我已经愉快地使用gson多年了,需要序列化和反序列化一些多态类型,并碰到了gson extra ,这似乎正是我所需要的:
但是无论我尝试什么,它都不会序列化类型字段,因此当它尝试反序列化时,自然会出现以下错误:
无法反序列化类<...>,因为它未定义名为type的字段
即使使用文件中的演示代码对我也不起作用:
class Shape {
int x;
int y;
}
class Diamond extends Shape {
int width;
int height;
}
...
Gson g = (new GsonBuilder()).registerTypeAdapterFactory(
RuntimeTypeAdapterFactory
.of(Shape.class)
.registerSubtype(Diamond.class)
).create();
Diamond d = new Diamond();
d.x = 10;
d.y = 20;
d.width = 25;
d.height = 35;
String json = g.toJson(d);
哪个会产生:
{“宽度”:25,“高度”:35,“ x”:10,“ y”:20}
请注意,我尝试为 of()和 register()指定自定义字符串,并将类型添加到 toJson()调用中,甚至将对象嵌入到外部集合中,但这没什么区别。
实际上,标准 Gson 对象与使用构建器和类型工厂创建的对象之间的输出没有差异。
我注意到,如果我调试代码并在 RuntimeTypeAdapterFactory 读写方法中设置断点,它将命中read()(然后到达上面的错误),但它从未命中写方法。只是完全跳过了。
这是怎么回事?我正在使用的代码是最新的,并且直接来自上面的链接(截至今天)。
答案 0 :(得分:2)
感谢贡献者对公共存储库的帮助,问题是需要包含基本类型的序列化步骤。因此,除了简单地:
g.toJson(d);
它必须是:
g.toJson(d, Shape.class);
我尝试过g.toJson(d, Diamond.class)
,但这对输出没有影响。希望这可以帮助其他人!
答案 1 :(得分:0)
rjcarr(在对toJson
的调用中包含类对象)的解决方案不切实际,因为通常将多态对象作为其他对象的成员或作为列表中的元素。
实际上RuntimeTypeAdapterFactory
中有一个错误。在this github post中,user ultraon提出了一个对我有用的解决方案:
替换
if (type.getRawType() != baseType)
使用
if (null == type || !baseType.isAssignableFrom(type.getRawType()))
第185行中的类create
的方法RuntimeTypeAdapterFactory
。
现在type属性包含在JSON中。