使用Jersey和Jackson对Map进行序列化和反序列化

cho*_*ouk 3 java json jax-rs jersey jackson

我有一个Pojo对象,由Jersey使用jackson序列化:

public class BookOfFriendsAnswer {
private Map<String, List<BookSummary>> books;

public BookOfFriendsAnswer() {

}

public BookOfFriendsAnswer(Map<String, List<BookSummary>> books) {
    this.books = books;
}

public Map<String, List<BookSummary>> getBooks() {
    return books;
}

public void setBooks(Map<String, List<BookSummary>> books) {
    this.books = books;
}
}
Run Code Online (Sandbox Code Playgroud)

序列化产生一个像这样的JSon:

{
  "books": {
    "entry": [
      {
        "key": "54567bbce4b0e0ef9379993e",
        "value": "BookSummary{id='54567bbde4b0e0ef9379993f', title='title 1', authors=[Steve,James] } BookSummary{id='54567bd9e4b0e0ef93799940', title='Title 2', authors=[Simon, Austin]}"
      }
    ]
  }
}
Run Code Online (Sandbox Code Playgroud)

但是,当我试图从我的客户端反序列化消息时,如下所示:

mapper.readValue(json, clazz)
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

无法识别的字段"key"(类com.example.server.api.BookSummary),未标记为可忽略

我不知道问题是来自服务器生成的JSOn还是客户端的反序列化.

你知道什么是问题以及如何纠正它?

非常感谢

Pau*_*tha 6

所以经过一些测试后:

  • Jersey 1.18.1(jersey-json-1.18.1支持JSON)
  • Jersey 2.13(jersey-media-json-jackson-2.13支持JSON)
  • Jersey 2.13(jersey-media-moxy-2.13支持JSON)

最后一次测试(jersey-media-moxy-2.13)是唯一一个产生这种精确输出的测试

{
  "books": {
    "entry": [
      {
        "key": "54567bbce4b0e0ef9379993e",
        "value": "BookSummary{id='54567bbde4b0e0ef9379993f', title='title 1', authors=[Steve,James] } BookSummary{id='54567bd9e4b0e0ef93799940', title='Title 2', authors=[Simon, Austin]}"
      }
    ]
  }
}
Run Code Online (Sandbox Code Playgroud)

话虽这么说,我会假设您使用的是Jersey 2.x版本.我不确定MOXy中是否有任何配置可以更好地支持这个用例,但为了简单起见,只需添加以下依赖项,并摆脱MOXy

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-jackson</artifactId>
    <version>${jersey-version}</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)

有了这个,您将获得正确的JSON输出

{ //  BookOfFriendsAnswer object
    "books": {  // Map<String, List<BookSummary>> books
        "randomKey": [  // String (key) , List<BookSummary> (value)
            {  // BookSummary object
                "id": "54567bbde4b0e0ef9379993f",
                "title": "Title 1",
                "authors": ["Steve", "James"]
            }
        ]
    }
}
Run Code Online (Sandbox Code Playgroud)

简单测试

资源方法

@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getResponse() {
    BookOfFriendsAnswer books = new BookOfFriendsAnswer();
    String id = "randomKey";  <===== Not sure if you want the key to be 
                                     the BookSummary id
    BookSummary summary = new BookSummary();
    summary.setId(id);
    summary.setTitle("Title 1");
    summary.getAuthors().add("Steve");
    summary.getAuthors().add("James");
    List<BookSummary> summaries = new ArrayList<>();
    summaries.add(summary);
    books.getBooks().put("randomKey", summaries);
    return Response.ok(books).build();
}
Run Code Online (Sandbox Code Playgroud)

使用ObjectMapper进行测试

@Test
public void testGetIt() throws Exception {
    String responseMsg = target.path("book").request().get(String.class);
    ObjectMapper mapper = new ObjectMapper();
    BookOfFriendsAnswer books = mapper.readValue(
            responseMsg, BookOfFriendsAnswer.class);
    System.out.println(books);
}
Run Code Online (Sandbox Code Playgroud)

不使用ObjectMapper进行测试 - 使用自动配置的Jackson提供程序

@Test
public void testGetIt() throws Exception {
    BookOfFriendsAnswer responseMsg
            = target.path("book").request().get(BookOfFriendsAnswer.class);
    System.out.println(responseMsg);
}
Run Code Online (Sandbox Code Playgroud)