Gson 泛型映射
在这篇文章中,我们将探讨 Gson 如何处理 Java 泛型。 泛型对于任何数据映射库都是一个挑战,因为它们带来了不确定性。 如果我们想查看 Java 泛型、用例和含义,请随时阅读 Wikipedia 文章。 Gson 设计得相当好,可以处理泛型,但是大家需要知道一些事情。 感兴趣的? 继续阅读!
泛型的序列化
让我们从更简单的序列化案例开始。 由于我们想将 Java 对象转换为 JSON,我们已经知道需要使用什么类型和映射,对吗?
嗯,不完全。 但是让我们开始使用最常用的泛型:Java 集合。 我们有两个列表,一个包含整数值,另一个包含字符串值。
正如在之前的文章中已经看到的,将 Java 对象转换为 JSON 通常是直接的 gson.toJson()
调用:
Gson gson = new Gson();
List<Integer> integerList = new ArrayList<>();
integerList.add(1);
integerList.add(2);
integerList.add(3);
List<String> stringList = new ArrayList<>();
stringList.add("1");
stringList.add("2");
stringList.add("3");
String integerJson = gson.toJson(integerList);
String stringJson = gson.toJson(stringList);
这通常也适用于此。 但是,不能保证一定会! 使用普通的标准 Java 类型,Gson 可以毫无问题地确定类型,但是当我们转换复杂的对象模型时,我们始终建议使用安全的 new TypeToken
:
Gson gson = new Gson();
List<Integer> integerList = new ArrayList<>();
integerList.add(1);
integerList.add(2);
integerList.add(3);
List<String> stringList = new ArrayList<>();
stringList.add("1");
stringList.add("2");
stringList.add("3");
Type integerType = new TypeToken<List<Integer>>() {}.getType();
Type stringType = new TypeToken<List<String>>() {}.getType();
String integerJson = gson.toJson(integerList, integerType);
String stringJson = gson.toJson(stringList, stringType);
new TypeToken
调用通过使用一个空的匿名内部类来创建一个类型文字。 这就是为什么该行看起来有点时髦并以 (){}
结尾的原因。
尽管如此,这将确保 Gson 知道正确的泛型类型,并且我们将得到完整的 JSON:
再一次,对于很多简单的情况,比如上面的那个,这不是必需的。 我们建议大家习惯使用 TypeToken
方法,以避免最终遇到的问题。
在查看反序列化之前,让我们再回顾一个 Java 集合之外的泛型示例。 我们的 Box 类非常简单,只包含一个在编译时未知类型的对象:
public class Box<T> {
private T boxContent;
public Box(T t) {
this.boxContent = t;
}
}
我们整洁的 Box 类可以处理我们扔给它的任何类型的对象类型。 正如我们上面提到的,如果想安全起见,即使在序列化期间也要使用 new TypeToken
方法。
Gson gson = new Gson();
Box<String> stringBox = new Box<>("String Type");
Box<Integer> integerBox = new Box<>(42);
Box<UserSimple> complexBox = new Box<>(new UserSimple("jiyik", "jiyik_onmpw@163.com", 26, true));
Type stringType = new TypeToken<Box<String>>() {}.getType();
Type integerType = new TypeToken<Box<Integer>>() {}.getType();
Type complexType = new TypeToken<Box<UserSimple>>() {}.getType();
String integerJson = gson.toJson(integerBox, integerType);
String stringJson = gson.toJson(stringBox, stringType);
String complexJson = gson.toJson(complexBox, complexType);
这将为创建的 Java 对象生成完美的 JSON 匹配。
我们保证,在反序列化过程中它会变得更有趣! 我们将在下一节中深入探讨细节。
泛型反序列化
假设我们从我们的 API 接收 JSON,它使用 Java 泛型。 例如,使用上一节中的 Box 类,我们可以期待以下 JSON:
{
"boxContent": {
"_name": "jiyik",
"age": 26,
"email": "jiyik_onmpw@163.com",
"isDeveloper": true,
"registerDate": "Jun 7, 2021 7:15:29 AM"
}
}
这个 JSON 很好地向我们展示了核心问题是什么。
Gson 需要知道 Box 的类型是什么,否则无法映射 JSON。 例如,如果 JSON 包含 Box<String>
,则它是一个完全不同的映射。
因此,我们需要在反序列化泛型时指定 Box 类型。 当然,我们为此使用 TypeToken
类。
String complexGenericJson = "{'boxContent':{'_name':'jiyik','age':26,'email':'jiyik_onmpw@163.com','isDeveloper':true,'registerDate':'Jun 7, 2021 7:15:29 AM'}}";
Type complexType = new TypeToken<Box<UserDate>>() {}.getType();
Gson gson = new Gson();
Box boxWithData = gson.fromJson(complexGenericJson, complexType);
Box<UserDate> boxWithoutData = gson.fromJson(complexGenericJson, Box.class);
只要我们可以非常具体地了解传入类型,即使它包含在一些 Java 泛型中,Gson 也应该能够映射它。
相关文章
Gson 通过@JsonAdapter 自定义(反)序列化
发布时间:2022/07/24 浏览次数:217 分类:编程语言
-
在这篇文章中,我们将展示如何简化(反)序列化的自定义。 所有这些选项都只能通过自定义 Gson 实例和一些样板代码获得。 Gson 2.7 引入了一个简单的注解,我们可以节省大量代码并获
Gson 自定义反序列化基础
发布时间:2022/07/21 浏览次数:81 分类:编程语言
-
在这篇文章中,我们将了解如何实现自定义 Gson 反序列化。 如果服务器以与客户端的应用程序数据模型不匹配的格式向我们发送数据,请继续阅读!
Gson 自定义实例创建器
发布时间:2022/07/14 浏览次数:121 分类:编程语言
-
在这篇文章中,我们将讨论自定义反序列化的另一个组件。 在过去的几篇文章中,我们探讨了如何自定义数据的序列化和反序列化。 在这两种情况下,我们都试图减轻服务器和客户端之
Gson 循环引用的映射
发布时间:2022/07/13 浏览次数:173 分类:编程语言
-
在这篇文章中,我们将讨论一个特别讨厌的话题:循环引用。 我们可能在计算机科学或图表数学课上听说过循环引用。 在更实际的解释中:它处理对象具有指向不同对象的嵌套属性的情
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