Gson 通过@JsonAdapter 自定义(反)序列化
在这篇文章中,我们将展示如何简化(反)序列化的自定义。 在过去的几篇文章中,我们演示了如何自定义序列化.html)、反序列化tml)以及如何利用实例创建器。
所有这些选项都只能通过自定义 Gson 实例和一些样板代码获得。 Gson 2.7 引入了一个简单的注解,我们可以节省大量代码并获得相同的结果。 如果大家对 @JsonAdapter
感兴趣,请继续阅读!
@JsonAdapter 注解
我们将在本教程中使用的
@JsonAdapter
注解仅受 Gson 2.7(或更高版本)支持!
如果大家阅读过我们之前关于自定义(反)序列化的博客文章,就会知道一般结构并不太复杂,但总是有几行样例代码:
GsonBuilder gsonBuilder = new GsonBuilder();
Type merchantListType = new TypeToken<List<Merchant>>() {}.getType();
JsonSerializer<List<Merchant>> serializer = ...;
gsonBuilder.registerTypeAdapter(merchantListType, serializer);
Gson customGson = gsonBuilder.create();
String customJSON = customGson.toJson(subscription);
上面的代码片段向我们展示了一个自定义序列化程序的示例。 我们仍然需要 JsonSerializer
接口的实现,但是可以简化它周围的其他代码。
自定义序列化
第一步是拉出上面代码片段中的 serializer
对象并将其移动到一个类中。 该类具有与匿名声明相同的设置,因为我们将其作为对象完成
public class MerchantListSerializer implements JsonSerializer<List<Merchant>> {
@Override
public JsonElement serialize(List<Merchant> src, Type typeOfSrc, JsonSerializationContext context) {
JsonArray jsonMerchant = new JsonArray();
for (Merchant merchant : src) {
jsonMerchant.add("" + merchant.getId());
}
return jsonMerchant;
}
}
一旦我们将它包装在一个公共类中,就可以在 @JsonAdapter
注解中使用它。 @JsonAdapter
注解 ,就像我们在之前的文章中探讨的其他注解一样,被添加到 Java 模型中。 在上面的示例中,我们需要更改包含 List<Merchant>
属性的模型。
例如:
public class UserSubscriptionAnnotation {
String name;
String email;
int age;
boolean isDeveloper;
// new!
@JsonAdapter(MerchantListSerializer.class)
List<Merchant> merchantList;
}
需要自定义序列化程序的属性将由 @JsonAdapter
注解增强。 注解只接受一个参数:类引用。 该类需要实现 JsonSerializer
或 JsonDeserializer
。
以下所有 Gson 转换都将使用我们的自定义(反)序列化。 我们将不再需要自定义 Gson 实例。 因此,以下代码段就足够了:
UserSubscriptionAnnotation subscription = new UserSubscriptionAnnotation(
"jiyik",
"jiyik_onmpw@163.com",
26,
true,
subscribedMerchants);
Gson gson = new Gson();
String fullJSON = gson.toJson(subscription);
我们可以完全摆脱 GsonBuilder
部分,只需使用默认的 new Gson()
实例
自定义反序列化
相同的方法和注释也适用于自定义反序列化。 如果大家查看我们自定义反序列化文章中的代码,就会发现以下设置代码:
GsonBuilder gsonBuilder = new GsonBuilder();
JsonDeserializer<UserDate> deserializer = ...;
gsonBuilder.registerTypeAdapter(UserDate.class, deserializer);
Gson customGson = gsonBuilder.create();
UserDate customObject = customGson.fromJson(userJson, UserDate.class);
再一次,替代解决方案是将其从具有注册类型适配器的自定义 Gson 实例更改为注解模型。
首先,我们必须将反序列化器提取到一个类中:
public class UserDateDeserializer implements 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
);
}
}
如大家所见,deserialize()
中的代码保持不变。
第二步,给模型添加注解:
@JsonAdapter(UserDateDeserializer.class)
public class UserDate {
private String _name;
private String email;
private boolean isDeveloper;
private int age;
private Date registerDate
}
与前面通过注解进行自定义序列化的示例略有不同的是,我们注解的是整个类,而不是特定的属性。 两种方法都是可能的和有用的!
反序列化现在简化为一行代码:
UserDate standardObject = new Gson().fromJson(userJson, UserDate.class);
超出@JsonAdapter 的范围:多种自定义
Java 注解的一个限制是我们只能为每个类(或属性)添加一个注解。 如果我们的模型或属性之一需要自定义序列化程序和自定义反序列化程序,则我们需要通过带有 registerTypeAdapter()
调用的自定义 Gson 实例继续使用很长时间。
总结
在本篇文章中,我们了解了如何使用 @JsonAdapter
注解来节省大量样例代码并简化代码库。 虽然它没有添加任何新功能,但它使我们的代码更清晰、更易于理解。
此外,它通过只为每个模型(和属性)允许一个注解来防止我们意外注册多个自定义(反)序列化器。
相关文章
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