Gson 自定义反序列化基础
在这篇文章中,我们将了解如何实现自定义 Gson 反序列化。 如果服务器以与客户端的应用程序数据模型不匹配的格式向我们发送数据,请继续阅读!
自定义反序列化
在现代应用程序中,API 以没有 Java 等效项或不适合我们的应用程序的结构发送数据是很常见的。 在这些情况下,拥有一个自定义反序列化器非常有用,它采用 JSON 消息的数据格式并将其转换为对 Java 端有用的东西。
例如,让我们看一下以下 JSON:
{
"year": 116,
"month": 5,
"day": 21,
"age": 26,
"email": "jiyik_onmpw@163.com",
"isDeveloper": true,
"name": "jiyik"
}
底部的四个属性是有意义的,并且在 Java 中具有直接等效性。 然而,前三个代表一个简单的日期对象。 当然,我们可以只创建一个 Java 模型,它也有三个 int 值。 但这在我们的应用程序中会非常不方便,因为我们总是必须处理将这三个组合成一个有目的的日期对象。
更好的方法是自定义反序列化并立即将它们组合到日期对象。 在应用程序中,我们永远不会知道服务器以这种格式发送它,并且我们可以抽象出服务器和客户端之间的差异。
在此示例中,我们的目标是使用以下 Java 模型:
public class UserDate {
private String name;
private String email;
private boolean isDeveloper;
private int age;
private Date registerDate;
}
自定义反序列化的方法几乎与自定义序列化相同。 因此,阅读自定义序列化可能会有所帮助。
简而言之,我们需要使用自定义 Gson 实例并调用 registerTypeAdapter()
方法。 registerTypeAdapter()
需要两个参数。 第一个是我们要定制的整体模型的类型。 第二个参数是类型化 JsonDeserializer
的实例。
GsonBuilder gsonBuilder = new GsonBuilder();
JsonDeserializer<UserDate> deserializer = ...; // will implement in a second
gsonBuilder.registerTypeAdapter(UserDate.class, deserializer);
Gson customGson = gsonBuilder.create();
UserDate customObject = customGson.fromJson(userJson, UserDate.class);
关键部分是 JsonDeserializer
的实现。 我们需要实现一个 deserialize()
方法。 它向我们传递一个 JsonElement,其中包含实际输入 JSON 和必须返回的预期类型。
根据输入的 JSON,我们必须创建 Java 模型。 在大多数情况下,Gson 可以自动为我们完成所有这些工作。 当我们需要自定义反序列化时,可能需要手动执行一些操作。
继续我们的示例,接下来我们需要从三个年、月和日属性创建一个 Java Date 对象。 我们还将映射所有其他四个属性并实例化我们完整的 Java 模型:
// 更改特定类型的序列化
JsonDeserializer<UserDate> deserializer = new JsonDeserializer<UserDate>() {
@Override
public UserDate deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
JsonObject jsonObject = json.getAsJsonObject();
Date date = new Date(
jsonObject.get("year").getAsInt(),
jsonObject.get("month").getAsInt(),
jsonObject.get("day").getAsInt()
);
return new UserDate(
jsonObject.get("name").getAsString(),
jsonObject.get("email").getAsString(),
jsonObject.get("isDeveloper").getAsBoolean(),
jsonObject.get("age").getAsInt(),
date
);
}
};
正如我们在上面看到的,我们调用 getAsJsonObject()
来访问更方便的 JsonElement 包装。 然后我们可以调用 get()
来访问模型属性的值。 我们可以根据类型使用各种方法访问该模型属性的值,例如 getAsBoolean()
。 最后,我们返回 UserDate 类的一个新实例。
根据数据的保证,我们可能需要使用 has()
检查 JsonObject 中是否存在模型属性。 否则,如果大家正在访问一个属性然后尝试获取它的值,则可能会遇到 NullPointerExceptions
。
总结
在这篇文章中,我们了解了如何自定义 Gson 反序列化。 调整一次映射通常比在整个应用程序中处理奇怪的数据格式更容易且更有效。 自定义反序列化可以为我们做到这一点。
相关文章
Gson 通过@JsonAdapter 自定义(反)序列化
发布时间:2022/07/24 浏览次数:217 分类:编程语言
-
在这篇文章中,我们将展示如何简化(反)序列化的自定义。 所有这些选项都只能通过自定义 Gson 实例和一些样板代码获得。 Gson 2.7 引入了一个简单的注解,我们可以节省大量代码并获
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