Gson 如何对嵌套对象进行映射
在 Gson -- Java-JSON 序列化和反序列化入门 这篇文章中,我们介绍了Gson的基本功能。 在这篇文章中,我们将更多地使用更真实的数据并查看嵌套对象。 我们将了解使用包含额外复杂数据的对象是很容易的。
嵌套对象序列化
我们喜欢通过示例演示功能,所以让我们扩展我们的 UserSimple 模型。 在之前的文章中,用户模型只有几个标准的 Java 类型:
public class UserSimple {
String name;
String email;
boolean isDeveloper;
int age;
}
现在我们的用户也有了一个家庭地址,它有自己的模型类 UserAddress
:
public class UserNested {
String name;
String email;
boolean isDeveloper;
int age;
// 新字段
UserAddress userAddress;
}
public class UserAddress {
String street;
String houseNumber;
String city;
String country;
}
换句话说,当前在 UserNested
模型中表示的用户与地址对象具有额外的一对一关系。 地址在 UserAddress
模型中表示。
在 Java 中,这两个模型可以通过类清晰地分开,我们通过 UserAddress userAddress
字段保留引用。 但是,在 JSON 中,我们没有类或引用。 JSON 中的唯一方法(以后不使用 ID 并将事物绑定在一起)是将用户地址嵌套在用户对象中。 基本上,在 JSON 中,我们只需在字段名称后使用 {}
创建一个新对象:
{
"age": 26,
"email": "jiyik_onmpw@163.com",
"isDeveloper": true,
"name": "jiyik",
"userAddress": {
"city": "beijing",
"country": "china",
"houseNumber": "42A",
"street": "Main Street"
}
}
与其他属性(age、email、...)不同,新的 userAddress
没有直接值。 相反,它有包含在 {}
中的子值。 立即将字段名称后面的括号理解为信号 this-is-a-nested-object 很重要。
理论够了。 是时候看看 Gson 从 UserNested
对象创建了什么。 我们可能会清晰的认出这种模式。 Gson 不需要任何配置。 它会根据传递的类自动推断数据的结构:
UserAddress userAddress = new UserAddress(
"Main Street",
"42A",
"BeiJing",
"China"
);
UserNested userObject = new UserNested(
"jiyik",
"jiyik_onmpw@163.com",
true,
26,
userAddress
);
Gson gson = new Gson();
String userWithAddressJson = gson.toJson(userObject);
userWithAddressJson
字符串的值很有趣:
{
"name": "jiyik",
"email": "jiyik_onmpw@163.com",
"isDeveloper": true,
"age": 26,
"userAddress": {
"street": "Main Street",
"houseNumber": "42A",
"city": "BeiJing",
"country": "China"
}
}
结果完全符合我们的预期。 Gson 正确创建了嵌套的 userAddress
JSON 对象。 当然,我们可以为用户的付款方式或工作地址添加更多的嵌套对象。 即使是嵌套对象也可以有嵌套对象!
在下一部分中,我们将看看另一个方向。 我们如何将复杂的嵌套 JSON 反序列化为 Java 对象?
嵌套对象反序列化
在上面,我们假设模型已经存在,我们只想创建一个匹配的 JSON。 尤其是对于现实世界中的应用程序开发人员来说,情况往往恰恰相反。 API 正在返回一些 JSON,我们需要为该 JSON 创建模型类。
如果大家已经阅读了这篇文章的前几段,那么大家已经对如何创建模型类有所了解。 下面的示例中我们转换一下场景,从用户示例转到一家不错的小餐厅。
{
"name": "迹忆客美食馆",
"owner": {
"name": "jiyik",
"address": {
"city": "BeiJing",
"country": "China",
"houseNumber": "42A",
"street": "Main Street"
}
},
"cook": {
"age": 18,
"name": "Tom",
"salary": 1500
},
"waiter": {
"age": 18,
"name": "Jerry",
"salary": 1000
}
}
这来自我们的 API,我们希望利用 Gson 自动为其创建匹配的 Java 对象。 首先,我们需要对所有一级字段所在的基类进行建模:
public class Restaurant {
String name;
Owner owner;
Cook cook;
Waiter waiter;
}
看看我们如何为 name 创建一个 String 并为其他三个创建额外的 Java 类? 每个人可能得出了不同的结果。 创建 Java 对象并不总是明确的。 例如,基于 JSON,我们看到 cook 和 waiter 嵌套对象具有相同的结构。 我们仍然可以创建一个不同的类,就像我们在上面所做的那样,或者为两者创建一个普通的 Staff 类:
public class Restaurant {
String name;
Owner owner;
Staff cook;
Staff waiter;
}
任何一个都可以。 如果有疑问,我们通常倾向于使用额外的类来避免将来出现并发的问题。 例如,如果厨师模型发生变化,但服务员模型保持不变,那就可能需要更改一堆代码。 因此,我们暂时放弃 Staff 的方案。 当然,我们仍然需要为二级对象创建 Java 模型类:
public class Owner {
String name;
UserAddress address;
}
public class Cook {
String name;
int age;
int salary;
}
public class Waiter {
String name;
int age;
int salary;
}
我们重新使用了第一部分的 UserAddress
。 因为它可以完美进行匹配;-)
尽管如此,我们希望大家了解从 JSON 字符串创建 Java 模型类的过程。 我们需要从顶层到最深层,直到嵌套的 JSON 只剩下常规类型。
主要工作已经完成,我们可以把所有东西都扔给 Gson。 当然,如果我们正确地完成了我们的工作,它将优雅地处理所有事情并只用几行代码创建 Java 对象:
String restaurantJson = "{ 'name':'迹忆客美食馆', 'owner':{ 'name':'jiyik', 'address':{ 'city':'BeiJing', 'country':'China', 'houseNumber':'42A', 'street':'Main Street'}},'cook':{ 'age':18, 'name': 'Tom', 'salary': 1500 }, 'waiter':{ 'age':18, 'name': 'Jerry', 'salary': 1000}}";
Gson gson = new Gson();
Restaurant restaurantObject = gson.fromJson(restaurantJson, Restaurant.class);
restaurantObject 实际上包含Json中的所有信息:
提示:从 JSON 创建 Java 模型类可能是一项乏味的工作。 在掌握了这些概念之后,大家可能想要使用自动化该过程的工具。 我们推荐 jsonschema2pojo.org 。
相关文章
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 格式的对象列表。 到目前为止,这没有什么不寻常的,也不是问题。 然而,问题是对象是多态的,需要解析子类特定的字段。 以