我在使用Gson序列化一个具有相同类型的类成员的对象时遇到了这个问题:
https://github.com/google/gson/issues/1447
对象:
public class StructId implements Serializable {
private static final long serialVersionUID = 1L;
public String Name;
public StructType Type;
public StructId ParentId;
public StructId ChildId;
由于StructId包含相同类型的ParentId/ChildId,因此在尝试序列化它时,我会得到无限循环,所以我所做的是:
private Gson gson = new GsonBuilder()
.setExclusionStrategies(new ExclusionStrategy() {
public boolean shouldSkipClass(Class<?> clazz) {
return false; //(clazz == StructId.class);
}
/**
* Custom field exclusion goes here
*/
public boolean shouldSkipField(FieldAttributes f) {
//Ignore inner StructIds to solve circular serialization
return ( f.getName().equals("ParentId") || f.getName().equals("ChildId") );
}
})
/**
* Use serializeNulls method if you want To serialize null values
* By default, Gson does not serialize null values
*/
.serializeNulls()
.create();
但这还不够好,因为我需要Parent/Child内部的数据,而忽略它们,而序列化不是一个解决方案。怎么可能解决呢?
与标记为解决方案的答案相关:
我有这样一个结构:- 结构1--表---变量1
序列化之前的对象是:
生成的Json是:
正如你所看到的,Table的ParentId是“Struct 1”,但是“Struct 1”的ChildId是空的,它应该是“Table”。
B.R.
4条答案
按热度按时间z4bn682m1#
我认为使用
ExclusionStrategy
不是解决这个问题的正确方法。我建议使用为
StructId
类定制的JsonSerializer
和JsonDeserializer
。(May使用
TypeAdapter
的方法会更好,但我没有足够的Gson经验来实现这一点。)因此,您可以通过以下方式创建
Gson
示例:下面的
StructIdSerializer
类负责将StructId
转换为JSON。它将其属性Name
,Type
和ChildId
转换为JSON。请注意,它不会将属性ParentId
转换为JSON,因为这样做会产生无限递归。下面的
StructIdDeserializer
类负责将JSON转换为StructId
。它将JSON属性Name
、Type
和ChildId
转换为StructId
中相应的Java字段。请注意,ParentId
Java字段是从JSON嵌套结构中重新构建的,因为它没有直接作为JSON属性包含。我用这个JSON输入示例测试了上面的代码
通过将其与
StructId root = gson.fromJson(new FileReader("example.json"), StructId.class);
,然后通过序列化,
System.out.println(gson.toJson(root));
并再次获得原始JSON。
kxe2p93d2#
这里只展示一种使用
TypeAdapter
和ExclusionStrategy
进行序列化的方法(因此我不处理反序列化)。这可能不是最漂亮的实现,但无论如何它是相当通用的。这个解决方案利用了这样一个事实,即你的结构是某种双向链表,给定该列表中的任何节点,我们只需要将父节点和子节点的序列化分开,这样它们就可以在一个方向上序列化,以避免循环引用。
首先,我们需要可配置的
ExclusionStrategy
,例如:那么
TypeAdapter
就像这样:测试它:
会给你给予这样的东西:
在我的测试材料中,名称默认初始化为
"name"+hashCode()
y0u0uwnf3#
对不起,误导了你们,基于这篇文章:
Is there a solution about Gson "circular reference"?
“Gson中没有循环引用的自动解决方案。我所知道的唯一一个自动处理循环引用的JSON生成库是XStream(带有Jettison后端)。
但前提是你不用Jackson!如果您已经在使用Jackson构建REST API控制器,那么为什么不使用它来进行序列化呢?无需外部组件,如:Gson或XStream。
Jackson的解决方案:
序列化:
反序列化:
最重要的是,您必须使用@JsonIdentityInfo注解:
eqfvzcg84#
如果你能接受二进制格式而不是json,你可以尝试https://github.com/alipay/fury。Json是一种文本格式,不能表示循环引用,必须通过@JsonIgnore注解来裁剪循环字段。但是json中的对象会丢失循环引用,被忽略的数据将为null。
使用fury进行循环引用序列化示例:
类似的框架如kryo/fst也可以用于此。