【发布时间】:2017-06-12 08:15:25
【问题描述】:
我有一个与后端微服务通信的 REST API 规范,它返回以下值:
关于“收藏”响应(例如 GET /users):
{
users: [
{
... // single user object data
}
],
links: [
{
... // single HATEOAS link object
}
]
}
关于“单一对象”响应(例如GET /users/{userUuid}):
{
user: {
... // {userUuid} user object}
}
}
选择这种方法是为了使单个响应可以扩展(例如,如果GET /users/{userUuid} 得到一个额外的查询参数,例如?detailedView=true,我们就会有额外的请求信息)。
从根本上说,我认为这是一种可以最大限度地减少 API 更新之间的重大更改的方法。然而,将这个模型转化为代码非常困难。
假设对于单个响应,我为单个用户提供以下 API 模型对象:
public class SingleUserResource {
private MicroserviceUserModel user;
public SingleUserResource(MicroserviceUserModel user) {
this.user = user;
}
public String getName() {
return user.getName();
}
// other getters for fields we wish to expose
}
这种方法的优点是我们可以仅公开内部使用的模型中的字段,我们有公共getter,但不能公开其他字段。然后,对于集合响应,我将有以下包装类:
public class UsersResource extends ResourceSupport {
@JsonProperty("users")
public final List<SingleUserResource> users;
public UsersResource(List<MicroserviceUserModel> users) {
// add each user as a SingleUserResource
}
}
对于单个对象响应,我们将有以下内容:
public class UserResource {
@JsonProperty("user")
public final SingleUserResource user;
public UserResource(SingleUserResource user) {
this.user = user;
}
}
这会产生JSON 响应,其格式符合本文顶部的 API 规范。这种方法的好处是我们只公开那些我们想要公开的字段。严重的缺点是我有一个 ton 的包装类飞来飞去,除了被 Jackson 读取以产生正确格式的响应之外,它们没有执行任何可辨别的逻辑任务。
我的问题如下:
我怎样才能概括这种方法?理想情况下,我希望有一个
BaseSingularResponse类(可能还有一个BaseCollectionsResponse extends ResourceSupport类),我的所有模型都可以扩展,但是看到 Jackson 似乎如何从对象定义中派生 JSON 键,我将不得不使用一些东西像Javaassist一样在运行时向基本响应类添加字段 - 我希望尽可能远离人类这种肮脏的黑客行为。有没有更简单的方法来实现这一点?不幸的是,一年后我的响应中可能会有数量不定的顶级 JSON 对象,所以我不能使用像 Jackson 的
SerializationConfig.Feature.WRAP_ROOT_VALUE这样的东西,因为它会将 everything 包装到单个根级对象中(据我所知)。对于类级别(而不仅仅是方法和字段级别)可能有类似
@JsonProperty的东西吗?
【问题讨论】:
标签: java json spring spring-boot jackson