关于java:使用JAX-RS和Jackson将JPA实体转换为REST表示的最佳方法

Best way to convert a JPA entity to REST representations using JAX-RS and Jackson

我正在寻找一种将一些JPA实体导出到RESTAPI的方法,但我不想每次都发送整个实体,而是只共享一些特定的字段,具体取决于入口点。下面是一个小例子:

假设我们有一个Author类,没有字段:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Entity
public class Author implements Serializable{

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = SEQUENCE)
    private Long id;

    @NotNull
    @Size(min = 1, message ="{required.field}")
    private String name;

    @NotNull
    @Size(min = 1, message ="{required.field}")
    private String country;

    private LocalDate birthDate;

    // getters and setters
}

假设我们有这个REST服务(只有两种方法):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
@Path("authors")
public class AuthorREST {

    @Inject
    private AuthorBC bc;

    @GET
    @Produces("application/json")
    public List<Author> find(@QueryParam("q") String query) throws Exception {

        List<Author> result;

        if (Strings.isEmpty(query)) {
            result = bc.findAll();
        } else {
            result =  bc.find(query);
        }
        return result;
    }

    @GET
    @Path("{id}")
    @Produces("application/json")
    public Author load(@PathParam("id") Long id) throws Exception {

        Author result = bc.load(id);

        if (result == null) {
            throw new NotFoundException();
        }

        return result;
    }
}

现在,这样,当调用API时,我将始终拥有4个字段。

我知道,如果我使用Jackson,我可以将@JsonIgnore设置为要忽略的字段,它们将始终被忽略。

但如果我希望这样做,在某些情况下,我的整个实体由一个服务返回,而在其他服务(或同一服务中的其他方法)中,只返回2或3个字段呢?

有办法吗?


@jsonview和mix-in

您已经知道可以使用诸如@JsonIgnore@JsonIgnoreProperties之类的注释来让jackson忽略一些属性。

您还可以检查@JsonView注释。有关如何将@JsonView与jax-rs一起使用的一些详细信息,请在这里查看。

如果修改JPA实体不是一个选项,那么考虑按照这个答案中的描述混合注释。

数据传输对象

数据传输对象(DTO)是一种创建的模式,其目的非常明确:将数据传输到远程接口,就像Web服务一样。这种模式非常适合RESTAPI,并且使用DTO,从长远来看,您将拥有更大的灵活性。一旦REST资源表示不需要具有与持久性对象相同的属性,就可以根据需要定制类。

为了避免使用样板代码,可以使用映射框架(如mapstruct)将RESTAPI DTO从持久性对象映射到持久性对象。

有关使用DTO的好处的详细信息,请检查以下答案:

  • 为什么要在RESTAPI中使用DTO
  • 使用定制的请求和响应类

要为DTO提供更好的名称,请检查以下答案:

  • 给你的DTO起有意义的名字

如果要将解析与JPA实体分离,并且只返回某些属性,则始终可以为此使用mixin。http://www.cowtowncoder.com/blog/archives/2009/08/entry_.htmlhttps://github.com/fasterxml/jackson-docs/wiki/jacksonmixinannotations

还有一件事。如果您希望一个服务中的事物是动态的,以返回另一个服务中的一个表示,以返回另一个表示。您的选择是编写一个自定义的JSON序列化程序!检查此日志以了解如何创建客户序列化程序:如何在Jackson中使用自定义序列化程序?


对于我自己来说,我发现使用@jsonview注释非常合适。因此,可以定义要在特定视图中呈现的字段。您可以在以下网址找到更多信息:http://wiki.fasterxml.com/jacksonjsonviews


我将使用spring data rest,然后使用apimodel注释隐藏不希望公开的属性。


我认为您可以使用Jersey框架编写一个定制的MessageBodyWriter,并且您可以按照自己的需要控制响应负载。在这里,为了管理响应负载,您必须编写几行代码。有关更多信息,请访问http://jysi.java. net /文档/最新/消息体工作者。