【发布时间】:2020-05-25 14:20:08
【问题描述】:
我已编辑问题以提供更清晰的说明。
我的问题陈述是如何自定义 Jackson 序列化在我的 REST 响应中发送的实体的方式,以使我的 JSON 不会变得太大/不可读?
考虑我有以下实体(或资源/模型等)
public class Department
{
private Long id;
private String name;
private Employee head;
/***
* Other fields, getters and setters
*/
}
还有一个,像这样
public class Employee {
private Long id;
private String name;
private Department department;
/***
* Other fields, getters and setters
*/
}
我有一个 REST API,可以通过他/她的 ID 获取员工,这是我调用它时的响应
GET /api/employees/2
{
"id":"2",
"name":"John Doe",
"department":{
"id":3,
"name":"Product Support",
"head":{
"id":1,
"name":"The Chairman",
"department":{
"id":1,
"name":"Executive",
"head":null
}
}
}
}
如您所见,响应很大(根据数据模型可能会变得非常大)。我想阻止序列化深入嵌套对象。
我更喜欢的 JSON 响应是:
GET /api/employees/2
{
"id":"2",
"name":"John Doe",
"department":{
"id":3,
"name":"Product Support",
}
}
我已经知道我可以在Department.head 上使用@JsonIgnore 注释,如下所示:
public class Department
{
private Long id;
private String name;
@JsonIgnore
private Employee head;
/***
* Other fields, getters and setters
*/
}
但是,这将永久跳过序列化 head 属性。例如,请参阅下面的 REST API 调用,添加 @JsonIgnore
GET /api/departments/3
{
"id":3,
"name":"Product Support",
}
// Here, I want the Full serialized form of the Department Object
所以,如您所见,问题是:当我调用GET /api/departments/3 时,我希望Department 对象被完全序列化。但是,当我调用GET /api/employees/2 时,我希望它跳过head 属性。在 Spring Boot 中使用时,如何在 Jackson 中实现这一点?
我还遇到了一个名为 Squiggly 的库,它使用类似 GraphQL 的查询语言来处理 API 响应,但我想知道是否可以不学习新库。
非常感谢
在 Abbin Varghese 回答后编辑
我将Employee 模型更改为以下模型:
public class Employee {
private Long id;
private String name;
@JsonIgnoreProperties({"head"})
private Department department;
/***
* Other fields, getters and setters
*/
}
在序列化时,这给了我以下 JSON 输出:
{
"id":"2",
"name":"John Doe",
"department":{
"id":3,
"name":"Product Support",
}
}
这里的 pro 是它解决了我的问题,而无需为我的模型编写单独的 DTO 类。
然而,con 是这样的:在这种情况下,我试图仅针对 head 属性跳过序列化,因此将其包含在 @JsonIgnoreProperties 注释中是有意义的。如果要跳过的属性列表比要序列化的属性列表长怎么办?例如,如果我的 Department 有 15 个属性,并且我希望只序列化其中的 3 个,那么在 @JsonIgnoreProperties 注释中包含要跳过的 12 个属性变得很困难。
是否有相反的注释(仅包括这些字段等)??
【问题讨论】:
-
我建议定义单独的对象(避免使用 db 对象)以从 get 请求中返回数据。由于映射操作,它增加了一些复杂性,但它允许为每次调用选择要返回的数据。
-
@SergiiZhevzhyk 这绝对是我们正在考虑的事情。但是,我想要一些可以快速完成的事情,因为为每个实体创建镜像对象需要时间。考虑到我们现在已经采用的方法,有什么快速的解决方案或我可以采取的方向吗?
-
@SergiiZhevzhyk 也就是说,即使我们创建单独的对象来从 get 请求返回数据,我的嵌套对象问题仍然存在?到那时,我的 JSON 响应将包含我的子对象的所有属性,无论我是否想要它们。
-
您需要类似 WarehouseResponse 和 ClientResponse 类的东西,它们之间不应有任何公共类。在这种情况下,可以控制 GET 方法中返回的内容。
标签: json spring-boot serialization jackson