【问题标题】:JAX-RS client inside a container ISO8601 date serialization容器 ISO8601 日期序列化内的 JAX-RS 客户端
【发布时间】:2018-05-04 15:29:27
【问题描述】:

我有一个带有 POST /items 端点的 JSON REST API,它需要一个像这样的对象:

{"name": "item_name", "timestamp": "2018-01-01T01:01:01.001"}

我需要从部署在 WildFly10 上的 JEE7 应用程序调用此端点。

为了在 Java 中为对象建模,我定义了一个简单的 DTO 类:

class ItemDTO {

  private String name;
  private LocalDateTime timestamp;

  // default constructor and getters/setters omitted for brevity
}

默认情况下,LocalDateTime 的序列化结果是一个复杂的 JSON 对象,而不是 ISO8601 字符串。

根据我在网上找到的内容,我添加了我的依赖项:

    <dependency>
        <groupId>com.fasterxml.jackson.datatype</groupId>
        <artifactId>jackson-datatype-jsr310</artifactId>
        <version>${jackson.version}</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.datatype</groupId>
        <artifactId>jackson-datatype-jdk8</artifactId>
        <version>${jackson.version}</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.jaxrs</groupId>
        <artifactId>jackson-jaxrs-json-provider</artifactId>
        <version>${jackson.version}</version>
    </dependency>

jackson.version = 2.7.4

ClientBuilder builder = ClientBuilder.newBuilder()
  .register(new RequestLogger())
  .register(
    new JacksonJsonProvider(
      new ObjectMapper()
        .registerModule(new JavaTimeModule()) 
        .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
        .configure(SerializationFeature.WRITE_DURATIONS_AS_TIMESTAMPS, false)
        .setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS"))
      , DEFAULT_ANNOTATIONS)
);

上面的代码配置了一个 clientBuilder 来构建配备 ObjectMapper 的客户端,它将 Java8 日期/时间类型序列化为 ISO8601 字符串。

Response creation = builder.build()
  .target("http://localhost:8080/my-api/v1.0/items")
  .request().accept(MediaType.APPLICATION_JSON)
  .post(Entity.entity(itemDTO, MediaType.APPLICATION_JSON));

意外地这个请求失败了,因为 ItemDTO 中包含的 LocalDateTime 仍然被序列化为一个复杂的 JSON 对象。

注意:我的 REST API 完全能够将 ISO8601 字符串反序列化为 LocalDateTime

注意:发出 POST 请求的代码如果不在容器内运行(即 LocalDateTime 被序列化为 ISO8601),则可以完美运行

【问题讨论】:

    标签: json rest jakarta-ee jackson jax-rs


    【解决方案1】:

    "如果不在容器内运行,发出 POST 请求的代码可以完美运行"

    您向客户注册的JacksonJsonProvider 很可能不是正在使用的那个。在容器中,RESTEasy 已经有一个自动注册到客户端的 Jackson 模块,这就是正在使用的模块。

    您可以使用ContextResolver,而不是配置ObjectMapper 并将其传递给提供程序。提供者将查找此解析器并从那里获取ObjectMapper

    @Provider
    public class ObjectMapperResolver implements ContextResolver<ObjectMapper> {
        private final ObjectMapper mapper;
    
        public ObjectMapperResolver() {
            mapper = new ObjectMapper();
            // configure mapper
        }
    
        @Override
        public ObjectMapper getContext(Class<?> cls) {
            return mapper;
        }
    }
    

    然后只需向客户端注册解析器。

    ClientBuilder builder = ClientBuilder.newBuilder()
            .register(ObjectMapperResolver.class)
    

    如果我怀疑的情况,已经有一个 JSON 提供程序在幕后自动注册,那么您将不需要注册另一个。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-02-13
      • 2016-01-06
      • 2016-12-06
      • 1970-01-01
      • 2023-04-04
      • 2016-02-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多