简体   繁体   English

Jackson和多接口继承

[英]Jackson and multiple interface inheritance

I'm trying to implement json serialization of the single entity to different views according to used interface. 我正在尝试根据使用的接口将单个实体的json序列化为不同的视图。 For example we have: 例如,我们有:

public interface BookBrief {
  long getId();
  String getTitle();
}

public interface BookPreview {
  long getId();
  String getAnnotation();
}

public class Book implements BookBrief, BookPreview {

  // class fields here

  public long getId() {...}

  public String getTitle() {...}

  public String getText() {...}

  public String getAnnotation() {...}

  // setters here
}


// service which results is serialized to json in Spring MVC controllers

public interface BookService {

  List<? extends BookBrief> getBooks();

  BookPreview getBookPreview(long id);

  Book getBook(long id);
}

BookService implementation always returns Book class (with unused fields set to null). BookService实现始终返回Book类(未使用的字段设置为null)。 To serialize interfaces I tried to use annotation @JsonSerialize(as = Interface.class) for each, but for all interfaces jackson always use only the first one listed in 'implements' expression. 为了序列化接口,我尝试为每个接口使用注解@JsonSerialize(as = Interface.class),但是对于所有接口,杰克逊始终仅使用“实现”表达式中列出的第一个接口。 Is there a way to configure jackson like I need? 有没有一种方法可以像我一样配置杰克逊? Or may be there is a better solution? 还是有更好的解决方案?

Seems like you have 2 options: 似乎您有2个选择:

  1. Write a custom Jackson Serializer 编写自定义的Jackson序列化器
  2. Use Jackson views, which looks like a more viable choice (full documentation could be found here ). 使用Jackson视图,看起来更可行(可以在此处找到完整的文档)。

With Views it could be implemented in 3 easy steps: 使用Views可以通过3个简单的步骤来实现:

  1. Define your view markers: 定义您的视图标记:

BookViews.java : BookViews.java

public class BookViews {

    public static class BookBrief { }

    public static class BookPreview { }

}
  1. Annotate which Book fields you want to be exposed in each view: 注释要在每个视图中公开的“图书”字段:

Book.java : Book.java

public class Book {

    @JsonView({BookViews.BookBrief.class, BookViews.BookPreview.class})
    private long id;

    @JsonView(BookViews.BookBrief.class)
    private String title;

    @JsonView(BookViews.BookPreview.class)
    private String annotation;

    // Constructors and getters/setters
}
  1. Annotate REST method with JSonValue and specify which view you want to use: 用JSonValue注释REST方法,并指定要使用的视图:

BookService.java : BookService.java

@Path("books")
public class BookService {

    private static final List<Book> library = Arrays.asList(
            new Book(1, "War and Peace", "Novel"),
            new Book(2, "A Game of Thrones", "Fantasy")
    );

    @GET
    @Path("all")
    @JsonView(BookViews.BookBrief.class)
    @Produces(MediaType.APPLICATION_JSON)
    public Response getBooks() {
        return Response.status(Response.Status.OK).entity(library).build();
    }

    @GET
    @Path("previews")
    @JsonView(BookViews.BookPreview.class)
    @Produces(MediaType.APPLICATION_JSON)
    public Response getBookPreviews() {
        return Response.status(Response.Status.OK).entity(library).build();
    }

}

Result : 结果

GET http://localhost:8080/root/rest/books/all : GET http:// localhost:8080 / root / rest / books / all

[
    {
        "id": 1,
        "title": "War and Peace"
    },
    {
        "id": 2,
        "title": "A Game of Thrones"
    }
]

GET http://localhost:8080/root/rest/books/previews : GET http:// localhost:8080 / root / rest / books / previews

[
    {
        "annotation": "Novel",
        "id": 1
    },
    {
        "annotation": "Fantasy",
        "id": 2
    }
]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM