Gson 循环引用的映射
在这篇文章中,我们将讨论一个特别讨厌的话题:循环引用。 我们可能在计算机科学或图表数学课上听说过循环引用。 在更实际的解释中:它处理对象具有指向不同对象的嵌套属性的情况,然后引用回原始对象。 这种情况会导致 Gson 使我们的应用程序崩溃。 如果想知道如何处理此问题,那么继续阅读吧!
Gson 和 StackOverflowError
这篇文章的替代标题可以是:为什么 Gson 会导致 java.lang.StackOverflowError?
只需从序列化的角度考虑:正如我们在嵌套对象文章中所了解到的,Gson 需要为每个引用的对象创建一个新的 JSON 子元素。 如果对象 A 引用对象 B,Gson 将需要在 A 中为 B 创建一个子元素。如果 B 引用回 A,我们将陷入无限循环,并将继续创建新的子元素,从而创建新的子元素,依此类推。 最终,这将触发 StackOverflowError
。
让我们用一些实际的代码来可视化这个场景:
public class UserCircular {
String name;
String email;
int age;
boolean isDeveloper;
// 对子节点和父节点的引用
UserCircular child;
UserCircular parent;
}
想象一下,我们的应用构建了一个家谱。 然后每个家庭成员都可能被包裹在上面你可以看到的 UserCircular
类中。 好吧,child 和 parent 属性可能应该是一个列表,但这不会改变任何东西。
从编程的角度来看,这是一个完全有效的实现。
UserCircular userObject = new UserCircular();
UserCircular child = new UserCircular();
userObject.setName("zhangsan");
userObject.setAge(46);
userObject.setEmail("jiyik_onmpw@163.com");
child.setName("zhangtian");
child.setAge(22);
child.setEmail("no");
child.setParent(userObject);
userObject.setChild(child);
Gson gson = new Gson();
String userJson = gson.toJson(userObject);
不幸的是,我们将无法对其进行序列化。 没有 JSON 等价物具有相同的数据格式,因为我们将陷入无限循环。导致出现 java.lang.StackOverflowError
错误
解决方案很简单:我们必须从序列化中排除一个图形引用。 一种简单的方法是将 transient 添加到 parent 属性:
public class UserCircular {
String name;
String email;
int age;
boolean isDeveloper;
// 对子节点和父节点的引用
UserCircular child;
transient UserCircular parent;
}
在内部,我们的应用程序没有任何变化。 尽管如此, parent 将不再被序列化,并且我们已退出该无限循环:
{
"name": "zhangsan",
"email": "jiyik_onmpw@163.com",
"age": 46,
"isDeveloper": false,
"child": {
"name": "zhangtian",
"email": "no",
"age": 22,
"isDeveloper": false
}
}
所有必要的数据仍将被序列化。 如果需要,服务器将需要再次创建反向引用。
总结
在这篇文章中,我们了解了 Gson 何时会陷入无限循环并抛出 StackOverflowError
。 我们可以通过从序列化中排除一个指针来解决此问题。
相关文章
Gson 通过@JsonAdapter 自定义(反)序列化
发布时间:2022/07/24 浏览次数:217 分类:编程语言
-
在这篇文章中,我们将展示如何简化(反)序列化的自定义。 所有这些选项都只能通过自定义 Gson 实例和一些样板代码获得。 Gson 2.7 引入了一个简单的注解,我们可以节省大量代码并获
Gson 自定义反序列化基础
发布时间:2022/07/21 浏览次数:81 分类:编程语言
-
在这篇文章中,我们将了解如何实现自定义 Gson 反序列化。 如果服务器以与客户端的应用程序数据模型不匹配的格式向我们发送数据,请继续阅读!
Gson 自定义实例创建器
发布时间:2022/07/14 浏览次数:121 分类:编程语言
-
在这篇文章中,我们将讨论自定义反序列化的另一个组件。 在过去的几篇文章中,我们探讨了如何自定义数据的序列化和反序列化。 在这两种情况下,我们都试图减轻服务器和客户端之
Gson Builder Floats 和 Doubles 的特殊值
发布时间:2022/07/12 浏览次数:193 分类:编程语言
-
在上一篇 Gson 的文章中,我们研究了使 JSON 转换降低标准的选项。 Lenient 允许传入的 JSON 在某种程度上是非标准的,Gson 仍然能够将其解析为 Java 对象。 在这篇文章中,我们将研究一个
Gson 自定义序列化
发布时间:2022/07/11 浏览次数:117 分类:编程语言
-
在这篇文章中,我们将探讨如何自定义 Java 对象的 Gson 序列化。 我们可能想要更改序列化的原因有很多,例如 简化我们的模型以减少发送的数据量或删除个人信息。 现在我们将通过实
Gson 映射 Enum 枚举
发布时间:2022/07/10 浏览次数:156 分类:编程语言
-
在之前的文章中我们介绍了如何映射嵌套对象、数组和列表、Java Map 等。 在这篇文章中,您将学习如何(反)序列化 Java 枚举 Enum。
Gson 如何反序列化多态对象列表
发布时间:2022/07/09 浏览次数:286 分类:编程语言
-
最近,我们遇到了一种情况,我从 REST 端点接收到 JSON 格式的对象列表。 到目前为止,这没有什么不寻常的,也不是问题。 然而,问题是对象是多态的,需要解析子类特定的字段。 以
Gson Builder 使用 Lenient 放宽 Gson 的转换标准
发布时间:2022/06/26 浏览次数:100 分类:编程语言
-
JSON 内容的格式必须满足一些特定的规则才能符合标准。 该标准在 RFC4627 规范中进行了描述。 它为键和值的分离方式、数组的结构等奠定了基础。 在这篇文章中,我们将探讨 Gson 与 J