Gson 自定义实例创建器
在这篇文章中,我们将讨论自定义反序列化的另一个组件。 在过去的几篇文章中,我们探讨了如何自定义数据的序列化和反序列化。 在这两种情况下,我们都试图减轻服务器和客户端之间数据模型的差异。
在这篇文章中,我们将研究两个模型相同的情况,但客户端具有额外的(帮助)属性或在反序列化数据时需要调用的特定构造函数。
Gson 实例创建器
默认情况下,Gson 将始终创建 Java 模型的空实例,然后通过反射设置属性。 严格来说,我们在模型中创建的构造函数根本不被使用(由 Gson 使用)。 如果您的 Java 模型充当简单的数据持有者并且不提供进一步的逻辑或功能,则此行为没有缺点。
但是,如果我们的数据模型确实具有默认或动态设置的其他属性,则您必须进行一些黑客攻击才能绕过 Gson 对反射的使用。 幸运的是,Gson 也涵盖了该用例,并允许您使用 InstanceCreators 实现一个干净的解决方案。
假设服务器发送一个相当简单的 JSON:
{
"age": 26,
"email": "jiyik_onmpw@163.com",
"isDeveloper": true,
"name": "jiyik"
}
我们的应用程序有一个等效的 Java 模型,Gson 可以映射它而无需任何进一步的定制。 但是,客户端模型中还有一个附加属性:Context
。 Context 可能是将该 Java 对象存储在数据库中所必需的。 它不会随 JSON 一起提供,映射它也没有任何意义。 它只是我们 Java 应用程序中的一个助手。
因此,我们的 Java 模型中只有一个构造函数,它需要 Context
对象:
public class UserContext {
private String name;
private String email;
private boolean isDeveloper;
private int age;
// 附加属性,不属于数据模型的一部分
private Context context;
public UserContext(Context context) {
this.context = context;
}
}
如果我们将上述模型与 Gson 的默认行为一起使用,则在反序列化后 context 将始终为 null。 在 Gson 进行映射之前,我们需要一种调用构造函数并设置 context 的方法。 正是为了这个目的,Gson 提供了 InstanceCreators
。
声明自定义 InstanceCreators
的方式与自定义序列化程序非常相似。
String userSimpleJson = ...; // 来自服务器的 JSON,见上文
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(
UserContext.class,
new UserContextInstanceCreator(getApplicationContext())
);
Gson customGson = gsonBuilder.create();
UserContext customObject = customGson.fromJson(userSimpleJson, UserContext.class);
我们正在使用一个自定义 Gson 实例并调用 registerTypeAdapter()
来添加一个新的实例创建器。 该方法需要两个参数。 首先,我们要调整的数据模型的类型。 其次,实例创建者的实现。
在我们的例子中,它是 UserContextInstanceCreator
类:
private class UserContextInstanceCreator implements InstanceCreator<UserContext> {
private Context context;
public UserContextInstanceCreator(Context context) {
this.context = context;
}
@Override
public UserContext createInstance(Type type) {
// create new object with our additional property
UserContext userContext = new UserContext(context);
// return it to gson for further usage
return userContext;
}
}
该类必须实现类型化的 InstanceCreator
接口并覆盖 createInstance(Type type)
方法。 UserContextInstanceCreator
的构造函数可以由我们自己定义。在这种情况下,我们希望将 Context 传递给每个模型,因此我们将其传递给 InstanceCreator
并将其存储在一个字段中。每当 Gson 创建 UserContext
模型的新实例时,实例创建者将调用 UserContext(context)
构造函数。
因此,UserContext 类的所有后续实例都将 Context 设置为我们传递给实例创建者的值。在常规 Java-JSON 映射期间,Gson 仍会使用反射来设置属性。
当然,大家可以在这里做很多其他的事情。除了 Context 之外,我们可能还需要传递许多其他附加参数。或者我们的构造函数做了一些初始化工作,需要执行。通过声明一个 InstanceCreator
,我们可以确保 Gson 实际上正在调用构造函数。如果大家有其他示例,请在评论中告诉我们!
总结
在这篇文章中,我们了解了自定义 InstanceCreators
是什么以及它们的用途。 设置非常简单,我们可以摆脱一些黑客攻击,使其与 Gson 的默认行为一起工作。 确保我们知道如何使用 InstanceCreators
,因为我们最终会需要它们。
相关文章
Gson 通过@JsonAdapter 自定义(反)序列化
发布时间:2022/07/24 浏览次数:217 分类:编程语言
-
在这篇文章中,我们将展示如何简化(反)序列化的自定义。 所有这些选项都只能通过自定义 Gson 实例和一些样板代码获得。 Gson 2.7 引入了一个简单的注解,我们可以节省大量代码并获
Gson 自定义反序列化基础
发布时间:2022/07/21 浏览次数:81 分类:编程语言
-
在这篇文章中,我们将了解如何实现自定义 Gson 反序列化。 如果服务器以与客户端的应用程序数据模型不匹配的格式向我们发送数据,请继续阅读!
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