Jersey 子资源将我的 API 包裹在额外的 JSON 层中 - 我为什么要这个?
Jersey subresource wraps my API in an extra layer of JSON - why would I want this?
作为示例,假设我正在创建一个 HTTP REST API,其行为如下:
Return所有员工的集合:
GET /employees/
[
{
"id": 1,
"name": "John",
"roles": [
{
"id": 20,
"responsibility": 1000
},
...
]
},
...
]
Return id 为 1 的员工表示:
GET /employees/1/
{
"id": 1,
"Name": "John",
"roles": [
{
"id": 20,
"responsibility": 1000
},
...
]
}
Return 员工角色的集合:
GET /employees/1/roles
[
{
"id": 20,
"responsibility": 1000
},
...
]
Return id 为 20 的角色表示:
GET /employees/1/roles/20
{
"id": 20,
"responsibility": 1000
}
这样我们就可以遍历员工表示的树了。除了 /roles 之外,可能还有许多其他员工端点。
我使用 Jersey 将其拆分为具有多个子资源的根资源,例如:
@Path("/employees")
public class EmployeesResource() {
...
@GET
@Path("/{employeeId}/roles")
public RolesResource getRoles(@PathParam("employeeId") long employeeId) {
return new RolesResource(employeeId);
}
}
当我 GET /employees
和 /employees/1
时,这会产生所需的 JSON 结果,但是当我 GET /employees/1/roles
时,我得到响应正文:
{
"roles": [
{
"id": 20,
"responsibility": 1000
},
...
]
}
Jersey 已将我的 Role 表示集合包装在某个对象中。注意:该对象似乎与RolesResource中的子资源资源方法的名称有关(例如,如果方法名为getRoles()
我得到{"roles": [...]}
,如果方法名为getFoo()
我得到 {"foo": [...]}
).
我的问题:泽西岛这样做一定是有原因的。为什么我希望我的代表像这样包装?如果没有充分的理由,我该如何摆脱它?
编辑:我正在使用 Dropwizard 版本 0.8.2,看起来 from maven 正在引入 Jersey 2.19。它使用 Jackson 作为 JSON 提供者——同样,从 maven 看来版本是 2.5.1。否 web.xml 因为这是一个 dropwizard 应用程序。
我不知道 dropwizard
但我知道 jackson
而且我目前正在使用 jersey 2.21,所以我希望我的设置与你的设置足够接近。
我猜你已经构建了你的 RolesResource
class 有点类似于这个(如果不是这样,请 post 它!)
public class RolesResource {
private Role[] roles;
//constructor, getters, setters...
}
其中 Role
类似于,
public class Role {
private Integer id;
private Integer responsibility;
//constructor, getters, setters...
}
如果是这种情况,如果你 return RolesResource
作为你服务的输出,你只会得到你描述的 json
,
{
"roles": [
{
...
},
...
]
}
因为该对象实际上有一个名为 roles
的数组 Role[]
。
但是,您也可以 return Role[]
作为服务的输出,
@Path("/employees")
public class EmployeesResource() {
...
@GET
@Path("/{employeeId}/roles")
public Role[] getRoles(@PathParam("employeeId") long employeeId) {
return (new RolesResource(employeeId)).getRoles();
}
}
然后输出将只是 Role
.
类型的对象数组
[
{
"id": ...,
"responsibility": ...
},
...
]
至于你的问题,哪个比另一个更有意义?我想这是一个选择问题;我通常更喜欢封装,这样在客户端更容易检查(因此我选择第一个解决方案),但我认为这没有太大区别。
希望对您有所帮助。
我明白了。我用 @GET
注释了子资源定位器(本例中的 EmployeesResource.getRoles()
)。删除该注释会产生所需的结果。 RolesResource 中的方法使用 HTTP 方法名称进行注释。
作为示例,假设我正在创建一个 HTTP REST API,其行为如下:
Return所有员工的集合:
GET /employees/
[
{
"id": 1,
"name": "John",
"roles": [
{
"id": 20,
"responsibility": 1000
},
...
]
},
...
]
Return id 为 1 的员工表示:
GET /employees/1/
{
"id": 1,
"Name": "John",
"roles": [
{
"id": 20,
"responsibility": 1000
},
...
]
}
Return 员工角色的集合:
GET /employees/1/roles
[
{
"id": 20,
"responsibility": 1000
},
...
]
Return id 为 20 的角色表示:
GET /employees/1/roles/20
{
"id": 20,
"responsibility": 1000
}
这样我们就可以遍历员工表示的树了。除了 /roles 之外,可能还有许多其他员工端点。
我使用 Jersey 将其拆分为具有多个子资源的根资源,例如:
@Path("/employees")
public class EmployeesResource() {
...
@GET
@Path("/{employeeId}/roles")
public RolesResource getRoles(@PathParam("employeeId") long employeeId) {
return new RolesResource(employeeId);
}
}
当我 GET /employees
和 /employees/1
时,这会产生所需的 JSON 结果,但是当我 GET /employees/1/roles
时,我得到响应正文:
{
"roles": [
{
"id": 20,
"responsibility": 1000
},
...
]
}
Jersey 已将我的 Role 表示集合包装在某个对象中。注意:该对象似乎与RolesResource中的子资源资源方法的名称有关(例如,如果方法名为getRoles()
我得到{"roles": [...]}
,如果方法名为getFoo()
我得到 {"foo": [...]}
).
我的问题:泽西岛这样做一定是有原因的。为什么我希望我的代表像这样包装?如果没有充分的理由,我该如何摆脱它?
编辑:我正在使用 Dropwizard 版本 0.8.2,看起来 from maven 正在引入 Jersey 2.19。它使用 Jackson 作为 JSON 提供者——同样,从 maven 看来版本是 2.5.1。否 web.xml 因为这是一个 dropwizard 应用程序。
我不知道 dropwizard
但我知道 jackson
而且我目前正在使用 jersey 2.21,所以我希望我的设置与你的设置足够接近。
我猜你已经构建了你的 RolesResource
class 有点类似于这个(如果不是这样,请 post 它!)
public class RolesResource {
private Role[] roles;
//constructor, getters, setters...
}
其中 Role
类似于,
public class Role {
private Integer id;
private Integer responsibility;
//constructor, getters, setters...
}
如果是这种情况,如果你 return RolesResource
作为你服务的输出,你只会得到你描述的 json
,
{
"roles": [
{
...
},
...
]
}
因为该对象实际上有一个名为 roles
的数组 Role[]
。
但是,您也可以 return Role[]
作为服务的输出,
@Path("/employees")
public class EmployeesResource() {
...
@GET
@Path("/{employeeId}/roles")
public Role[] getRoles(@PathParam("employeeId") long employeeId) {
return (new RolesResource(employeeId)).getRoles();
}
}
然后输出将只是 Role
.
[
{
"id": ...,
"responsibility": ...
},
...
]
至于你的问题,哪个比另一个更有意义?我想这是一个选择问题;我通常更喜欢封装,这样在客户端更容易检查(因此我选择第一个解决方案),但我认为这没有太大区别。
希望对您有所帮助。
我明白了。我用 @GET
注释了子资源定位器(本例中的 EmployeesResource.getRoles()
)。删除该注释会产生所需的结果。 RolesResource 中的方法使用 HTTP 方法名称进行注释。