首页 > 解决方案 > 无法使用 Jackson 解组 LocalDate 和 LocalTime 类

问题描述

我正在使用 akka 制作一个 POST 路由,我将我的 Json 数据反序列化为 Video 对象,但以下 curl 请求:

curl -H "Content-Type: application/json" -X POST -d '{"title": "Video Title","videoDate":"10-2-2018","videoTime":"12:10:11"}' http://localhost:9090/updatedData

给出一个错误:Cannot unmarshal JSON as Video

当我从 json 中删除 videoDate 和 videoTime 字段时,请求工作正常。

Jackson.unmarshaller(VideoInfo.class)

//Video.class
public class Video {
    private String title;
    private LocalDate videoDate;
    private LocalTime videoTime;
}

使用的 Maven 依赖项是

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>2.9.8</version>
</dependency>

这是我的路线/updatedData

post(() ->
      path("updatedData", () -> {
          LOGGER.info("calling POST /updatedData");
          return entity(Jackson.unmarshaller(Video.class), videoInfo -> {
              LOGGER.debug("Payload received : " + videoInfo.toString());
              ArrayList<HttpHeader> headers = getCORSHeaders();
              return respondWithHeaders(headers, () ->
                                        onSuccess(videoFrameProcessing.updateVideoInfo(videoInfo), this::complete));
                            });
                        })),

标签: javajsonakkaunmarshallingakka-http

解决方案


Jackson 需要一个用于 Java 8 API的附加模块。 模块Time

jackson-datatype-jsr310

已被弃用,现在是

jackson-modules-java8

<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
    <version>2.9.8</version>
</dependency>

这意味着您需要手动注册该模块

final ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());

AkkaJackson类提供了 的重载版本unmarshaller,您可以使用它来传递自定义版本的ObjectMapper

public static <T> Unmarshaller<HttpEntity, T> unmarshaller(ObjectMapper mapper, Class<T> expectedType) {
  return Unmarshaller.forMediaType(MediaTypes.APPLICATION_JSON, Unmarshaller.entityToString())
                     .thenApply(s -> fromJSON(mapper, s, expectedType));
}

所以,而不是

Jackson.unmarshaller(Video.class)

利用

Jackson.unmarshaller(objectMapper, Video.class);

objectMapper参数为自定义ObjectMapper

final ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());

完整的片段将是

post(() ->
   path("updatedData", () -> {
      LOGGER.info("calling POST /updatedData");

      final ObjectMapper objectMapper = new ObjectMapper();
      objectMapper.registerModule(new JavaTimeModule());

      return entity(Jackson.unmarshaller(objectMapper, Video.class), videoInfo -> {
          LOGGER.debug("Payload received : " + videoInfo.toString());
          ArrayList<HttpHeader> headers = getCORSHeaders();
          return respondWithHeaders(headers, () ->
                       onSuccess(videoFrameProcessing.updateVideoInfo(videoInfo), this::complete));
     });
 })),

显然,将 提取ObjectMapper为“全局”变量。


推荐阅读