在 Quarkus + JSONB 中是否有类似于 Jackson + Spring 的 `@JsonView` 的等效功能?

huangapple go评论124阅读模式
英文:

Is there an equivalent of Jackson + Spring's `@JsonView` using Quarkus + JSONB?

问题

我正在使用 Quarkus 进行开发,并尝试构建一个 CRUD REST 应用程序;我想要获取两个端点,返回同一实体的两个不同视图。以下是在使用 Spring + Jackson 时的示例:

@Entity
public class Car{
  public String model;
  @ManyToOne( fetch = FetchType.LAZY, cascade = {CascadeType.ALL})
  public Owner owner;
  // [...]
}

@Entity
public class Owner{
  public String name;
  // [...]
}

以下是重要部分: 现在如果我在使用 Jackson,我会创建一个 CarView 类:

public class CarView {
  public static class Public {};
  public static class Private extends Public {};
}

然后,我会用 @JsonView(CarView.Public.class) 注解 Car.model,用 @JsonView(CarView.Private.class) 注解 Car.owner,然后在 REST 控制器中的方法上使用相同的注解,以告诉 Jackson 我想要使用哪个视图:

@RequestMapping("/car/{id}")
@JsonView(CarView.Public.class)
public Car getPublic(@PathVariable int id) { /*...*/ }

@RequestMapping("/car/private/{id}")
@JsonView(CarView.Private.class)
public Car getPrivate(@PathVariable int id) { /*...*/ }

我是否可以使用 Quarkus 和 JSON-B 实现相同的结果?

英文:

I'm playing with Quarkus and trying to build a CRUD REST application; I'm trying to get 2 endpoints returning 2 different views of the same entities. Here is an example on how I would have done in Spring + Jackson:

@Entity
public class Car{
  public String model;
  @ManyToOne( fetch = FetchType.LAZY, cascade = {CascadeType.ALL})
  public Owner owner;
  // [...]
}

@Entity
public class Owner{
  public String name;
  // [...]
}

Here it is the important part: now if I were using Jackson I would have create a CarView class:

public class CarView {
  public static class Public {};
  public static class Private extends Public {};
}

And with that I would have annotated Car.model with @JsonView(CarView.Public.class) and Car.owner with @JsonView(CarView.Private.class) and then just annotate with the same annotations my methods in the REST controller in order to tell Jackson which view I want to use:

@RequestMapping("/car/{id}")
@JsonView(CarView.Public.class)
public Car getPublic(@PathVariable int id) { /*...*/ }

@RequestMapping("/car/private/{id}")
@JsonView(CarView.Private.class)
public Car getPrivate(@PathVariable int id) { /*...*/ }

Can I accomplish the same result using Quarkus & JSON-B?

答案1

得分: 1

Quarkus支持使用JsonViews来管理请求/响应的序列化和反序列化。

(只是想让您知道,可悲的是,smallry-openapi实现目前尚不支持,所以即使序列化可以工作,您在Swagger中仍将看到完整的模型。)

使用示例,取自官方指南https://quarkus.io/guides/resteasy-reactive#jsonview-support:

JAX-RS方法可以使用@JsonView进行注释,以便根据每个方法的情况自定义返回的POJO的序列化。通过示例最好解释这一点。

@JsonView的典型用途是在特定方法上隐藏某些字段。在这方面,让我们定义两个视图:

public class Views {

    public static class Public {
    }

    public static class Private extends Public {
    }
}

假设我们有一个User POJO,我们想在序列化过程中隐藏某些字段。一个简单的示例是:

public class User {

    @JsonView(Views.Private.class)
    public int id;

    @JsonView(Views.Public.class)
    public String name;
}

根据返回此用户的JAX-RS方法,我们可能希望在序列化过程中排除id字段 - 例如,您可能希望不公开此字段的不安全方法。我们可以在RESTEasy Reactive中实现这一目标,如下例所示:

@JsonView(Views.Public.class)
@GET
@Path("/public")
public User userPublic() {
    return testUser();
}

@JsonView(Views.Private.class)
@GET
@Path("/private")
public User userPrivate() {
    return testUser();
}

当对userPublic方法的结果进行序列化时,响应中将不包含id字段,因为Public视图不包括它。然而,userPrivate的结果将如预期的那样在序列化时包含id字段。

英文:

Quarkus supports usage of JsonViews to manage the serialization/deserialization of request/response.

(Just to let you know, sadly it's not supported (yet) by smallry-openapi implementation, so even if the serialization would work, you'll still see the full model in swagger.)

An example of usage, taken from official guide https://quarkus.io/guides/resteasy-reactive#jsonview-support:

JAX-RS methods can be annotated with @JsonView in order to customize the serialization of the returned POJO, on a per method-basis. This is best explained with an example.

A typical use of @JsonView is to hide certain fields on certain methods. In that vein, let’s define two views:

public class Views {

    public static class Public {
    }

    public static class Private extends Public {
    }
}

Let’s assume we have the User POJO on which we want to hide some field during serialization. A simple example of this is:

public class User {

    @JsonView(Views.Private.class)
    public int id;

    @JsonView(Views.Public.class)
    public String name;
}

Depending on the JAX-RS method that returns this user, we might want to exclude the id field from serialization - for example you might want an insecure method to not expose this field. The way we can achieve that in RESTEasy Reactive is shown in the following example:

@JsonView(Views.Public.class)
@GET
@Path("/public")
public User userPublic() {
    return testUser();
}

@JsonView(Views.Private.class)
@GET
@Path("/private")
public User userPrivate() {
    return testUser();
}

When the result the userPublic method is serialized, the id field will not be contained in the response as the Public view does not include it. The result of userPrivate however will include the id as expected when serialized.

答案2

得分: 1

你有检查过@JsonbVisibility或者在 https://javaee.github.io/jsonb-spec/users-guide.html 中关于 "Jsonb adapter" 部分的内容吗?我担心在 Jsonb 中可能还没有像 Jackson 中的 @JsonView 那样的解决方案。Jsonb 适配器是在 bean 级别进行配置的(在进行序列化和反序列化时选择 Jsonb 实例),而不是在视图级别进行配置。

英文:

Have you checked @JsonbVisibility or "Jsonb adapter" part in
https://javaee.github.io/jsonb-spec/users-guide.html annotation from Jsonb? I am afraid maybe there isn't a solution in Jsonb yet like @JsonView in Jackson. Jsonb adapter is configuration at bean level(you choose the Jsonb instance when you (de)serialize), not at view level.

huangapple
  • 本文由 发表于 2020年9月3日 23:00:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/63726364.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定