使用GSON将复杂对象(去)序列化为JSON。

问题描述 投票:3回答:1

我在使用GSON对我的对象结构进行序列化和反序列化时遇到了一个问题。为了描述这个问题,我必须描述一下我的类结构。

我有一个java抽象类,我们把它命名为 "A". 还有 "BA"、"CA"、"DA "等类也是抽象的,它们扩展了 "A "类。它们每个类都有自己的构造函数,非但不是arg。最后还有几个(很多!)类,它们扩展了 "BC",或 "CA "或 "DA"。这些 "底层 "类的实例被保存在 "ArrayList "列表中。

现在,我试图将这个数组列表 "json化"。为了创建Json字符串,我使用了这段代码。

Gson gs = new Gson();
Type listOfTestObject = new TypeToken<List<A>>(){}.getType();
String rez = gs.toJson(getListOfAs(), listOfTestObject);

我试图用这个(在另一个类中)来反序列化Json:

Type listOfTestObject = new TypeToken<ArrayList<A>>(){}.getType();
ArrayList<A> listOfAs = gs.fromJson(jsonREZString, listOfTestObject);

但上面的代码却抛出了这个:

Unable to invoke no-args constructor for class packagename.A. Register an InstanceCreator with Gson for this type may fix this problem.

现在,我在 "A "类中创建了一个非args的构造函数,但是没有成功。我读过 "InstanceCreator",但看起来我必须为每个扩展 "A "的具体类创建一个 "InstanceCreator"。是吗?我不能这样做,因为我有很多(很多!)类通过 "BA"、"CA "或 "DA "来扩展 "A"。

我错过了什么?我怎样才能简单地反序列化(序列化似乎不错)这个复杂的结构,而不为每个类型添加自定义的反序列化代码?

java json gson
1个回答
3
投票

事实上,你在这里可能有2个不同的问题。

1) 你有多态类型,因此你可能想把对象序列化为他们的具体类型,而不是A.2) 你想反序列化为不提供无arg ctrs的具体类型。

Gson不支持1 & 2,有一个1的扩展,但我从来没有用过它。

也许可以 Genson 解决了你的问题,它同时支持1 & 2。

Genson genson = new Genson.Builder()
                            // enables polymorphic types support
                            .setWithClassMetadata(true)
                            // enables no arg support
                            .setWithDebugInfoPropertyNameResolver(true)
                          .create();

// will look like: [{"@class": "com.xxx.SomeConcreteClass", ...}, {"@class": "com.XXX.OtherClass"}]
String json = genson.serialize(getListOfAs());
List<A> listOfA = genson.deserialize(json, new GenericType<List<A>>() {});

你不需要在序列化过程中指定类型,除非你想让输出中只出现父字段。

例:genson.serialize(getListOfAs(),GenericType>(){})将只序列化A的属性,你也可以通过在构建器上设置UseRuntimeTypeForSerialization(true)来强制genson始终使用运行时类型。

另外,如果你不想让 impl 的细节泄露在 json 表示中,你可以为你的类型定义别名(builder.addAlias("someAlias", SomeClass.class),它们将被用来代替完整的包+类名。

© www.soinside.com 2019 - 2024. All rights reserved.