简体   繁体   English

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

[英]Complex object (de)serialization into JSON using GSON

I have a problem with serializing and deserializing my object structure with GSON.我在使用 GSON 序列化和反序列化我的对象结构时遇到问题。 In order to describe the problem i'll have to describe my class structure a bit:为了描述这个问题,我必须稍微描述一下我的类结构:

I have a java abstract class, let's name it "A".我有一个 Java 抽象类,我们将其命名为“A”。 There are also classes "BA", "CA", "DA" that are abstract too and they extend class "A".还有类“BA”、“CA”、“DA”也是抽象的,它们扩展了类“A”。 Each of them has it's own constructor, non of which is non-arg.他们每个人都有自己的构造函数,其中非非参数。 Finally there are several (many!) classes those extend "BC", or "CA" or "DA".最后有几个(很多!)类扩展了“BC”、“CA”或“DA”。 Instances of those "bottom" classes are kept in "ArrayList" list.这些“底部”类的实例保存在“ArrayList”列表中。

Now, i'm trying to "jsonize" that array list.现在,我正在尝试“jsonize”该数组列表。 For creating Json string I'm using this code:为了创建 Json 字符串,我正在使用以下代码:

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

And i'm trying to deserialize that json using this (in another class):我正在尝试使用它(在另一个类中)反序列化该 json:

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

but above code throws this:但上面的代码抛出这个:

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

Now, I have create a non-args constructor in the class "A", but no luck.现在,我在“A”类中创建了一个非参数构造函数,但没有运气。 I have read about "InstanceCreator" but it looks like I would have to create an "InstanceCreator" for each concrete class that extends "A"!我已经阅读了“InstanceCreator”,但看起来我必须为每个扩展“A”的具体类创建一个“InstanceCreator”! Right?对? I can't do it, because I have many (many!) classes that extend "A" through "BA", "CA" or "DA".我做不到,因为我有很多(很多!)类将“A”扩展到“BA”、“CA”或“DA”。

What am I missing?我错过了什么? How can I simply deserialize (serialization seems fine) this complex structure without adding custom deserialializastion code for each type?如何在不为每种类型添加自定义反序列化代码的情况下简单地反序列化(序列化看起来很好)这个复杂的结构?

In fact you might have here 2 distinct problems.事实上,您在这里可能有 2 个不同的问题。

1) You have polymorphic types thus you probably want to serialize objects as their concrete type and not A. 2) You want to deserialize to the concrete types that do not provide no arg ctrs. 1) 您有多态类型,因此您可能希望将对象序列化为它们的具体类型而不是 A。2) 您希望反序列化为不提供任何 arg ctrs 的具体类型。

Gson does not support 1 & 2, there is an extension for 1 but I never used it. Gson 不支持 1 和 2,有 1 的扩展,但我从未使用过它。

Maybe Genson solves your problem, it supports both 1 & 2.也许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>>() {});

You don't need to specify the type during serialization, except if you want that only parent fields be present in the output.您不需要在序列化期间指定类型,除非您希望输出中只存在父字段。

ex: genson.serialize(getListOfAs(), GenericType>() {}) will serialize only attributes from A, you can also force genson to always use runtime types by setting setUseRuntimeTypeForSerialization(true) on the builder.例如: genson.serialize(getListOfAs(), GenericType>() {}) 将仅序列化来自 A 的属性,您还可以通过在构建器上设置 setUseRuntimeTypeForSerialization(true) 来强制 genson 始终使用运行时类型。

Also if you don't want impl details to leak in the json representation, you can define aliases (builder.addAlias("someAlias", SomeClass.class) for your types, they will be used instead of full package+classname.此外,如果您不希望 impl 详细信息在 json 表示中泄漏,您可以为您的类型定义别名(builder.addAlias("someAlias", SomeClass.class),它们将用于代替完整的包+类名。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM