gpt4 book ai didi

java - Spring 启动 : Wrapping JSON response in dynamic parent objects

转载 作者:IT老高 更新时间:2023-10-28 13:54:00 24 4
gpt4 key购买 nike

我有一个与后端微服务通信的 REST API 规范,它返回以下值:

关于“Collection ”响应(例如 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
}

这种方法的优点是我们可以公开内部使用的模型中的字段,我们有公共(public)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 之类的东西。因为这会将 所有内容 包装到单个根级对象中(据我所知)。

  • 可能有类似 @JsonProperty 的东西吗?对于类级别(而不仅仅是方法和字段级别)?

最佳答案

有几种可能。

您可以使用 java.util.Map:

List<UserResource> userResources = new ArrayList<>();
userResources.add(new UserResource("John"));
userResources.add(new UserResource("Jane"));
userResources.add(new UserResource("Martin"));
Map<String, List<UserResource>> usersMap = new HashMap<String, List<UserResource>>();
usersMap.put("users", userResources);
ObjectMapper mapper = new ObjectMapper();
System.out.println(mapper.writeValueAsString(usersMap));

您可以使用 ObjectWriter 来包装您可以使用的响应,如下所示:

ObjectMapper mapper = new ObjectMapper();
ObjectWriter writer = mapper.writer().withRootName(root);
result = writer.writeValueAsString(object);

这是一个概括这种序列化的命题。

处理简单对象的类:

public abstract class BaseSingularResponse {

private String root;

protected BaseSingularResponse(String rootName) {
this.root = rootName;
}

public String serialize() {
ObjectMapper mapper = new ObjectMapper();
ObjectWriter writer = mapper.writer().withRootName(root);
String result = null;
try {
result = writer.writeValueAsString(this);
} catch (JsonProcessingException e) {
result = e.getMessage();
}
return result;
}
}

处理集合的类:

public abstract class BaseCollectionsResponse<T extends Collection<?>> {
private String root;
private T collection;

protected BaseCollectionsResponse(String rootName, T aCollection) {
this.root = rootName;
this.collection = aCollection;
}

public T getCollection() {
return collection;
}

public String serialize() {
ObjectMapper mapper = new ObjectMapper();
ObjectWriter writer = mapper.writer().withRootName(root);
String result = null;
try {
result = writer.writeValueAsString(collection);
} catch (JsonProcessingException e) {
result = e.getMessage();
}
return result;
}
}

还有一个示例应用程序:

public class Main {

private static class UsersResource extends BaseCollectionsResponse<ArrayList<UserResource>> {
public UsersResource() {
super("users", new ArrayList<UserResource>());
}
}

private static class UserResource extends BaseSingularResponse {

private String name;
private String id = UUID.randomUUID().toString();

public UserResource(String userName) {
super("user");
this.name = userName;
}

public String getUserName() {
return this.name;
}

public String getUserId() {
return this.id;
}
}

public static void main(String[] args) throws JsonProcessingException {
UsersResource userCollection = new UsersResource();
UserResource user1 = new UserResource("John");
UserResource user2 = new UserResource("Jane");
UserResource user3 = new UserResource("Martin");

System.out.println(user1.serialize());

userCollection.getCollection().add(user1);
userCollection.getCollection().add(user2);
userCollection.getCollection().add(user3);

System.out.println(userCollection.serialize());
}
}

你也可以在类级别使用Jackson注解@JsonTypeInfo

@JsonTypeInfo(include=As.WRAPPER_OBJECT, use=JsonTypeInfo.Id.NAME)

关于java - Spring 启动 : Wrapping JSON response in dynamic parent objects,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41880572/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com