【问题标题】:Serialization and deserialization of Map with Jersey and Jackson使用 Jersey 和 Jackson 对 Map 进行序列化和反序列化
【发布时间】:2015-01-05 06:18:37
【问题描述】:

我有一个 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;
}
}

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

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

但是,当我尝试像这样反序列化来自客户端的消息时:

mapper.readValue(json, clazz)

我收到以下错误:

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

不知道是服务端生成的JSon还是客户端反序列化的问题。

你知道问题出在哪里以及如何解决吗?

非常感谢

【问题讨论】:

  • 1. value 应该是一个数组,而不是字符串 2. BookSummary 类的字段应该与 value 3 兼容。您必须将哪个 json 字段提供反序列化。
  • 你能发布你的依赖

标签: java json jersey jackson jax-rs


【解决方案1】:

所以经过一些测试:

  • 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]}"
      }
    ]
  }
}

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

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-jackson</artifactId>
    <version>${jersey-version}</version>
</dependency>

这样,您将获得正确的 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"]
            }
        ]
    }
}

简单测试

资源方式

@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();
}

使用 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);
}

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

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

【讨论】:

  • 非常感谢您的调查。事实上,我正在使用 jersey-media-moxy 并用 jersey-media-json-jackson 替换这个依赖项纠正了我的问题。谢谢!!
【解决方案2】:

我认为您应该创建特定的 Map 类型并将其提供给反序列化过程:

TypeFactory typeFactory = mapper.getTypeFactory();
MapType mapType = typeFactory.constructMapType(HashMap.class, String.class, ArrayList.class);
HashMap<String, List<BookSummary>> map = mapper.readValue(json, mapType);

【讨论】:

    猜你喜欢
    • 2014-05-19
    • 1970-01-01
    • 2021-12-13
    • 1970-01-01
    • 2016-12-11
    • 1970-01-01
    • 2013-12-05
    • 2014-07-27
    • 2019-10-25
    相关资源
    最近更新 更多