【问题标题】:Convert Instant to ISO8601 date format not working in Spring Boot将 Instant 转换为 ISO8601 日期格式在 Spring Boot 中不起作用
【发布时间】:2021-02-09 18:29:22
【问题描述】:

我正在使用 spring boot 2.3.4.RELEASE,当尝试将包含 Instant 属性的 DTO 转换为 JSON 格式时,jackson ObjectMapper 不断将其转换为时间戳格式,即使打开了 write-dates-as-timestamps 选项关闭。

pom.xml

<parent>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-parent</artifactId>
     <version>2.3.4.RELEASE</version>
     <relativePath/> <!-- lookup parent from repository -->
</parent> 

....

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

application.properties

spring.jackson.serialization.write-dates-as-timestamps = false

DTO:

@Data
public class MyDTO {

    Long id;

    @NotNull
    String number;

    @NotNull
    Integer year;

    @NotNull
    VesselContractStatusEnum status;

    Instant statusDate;
}

休息控制器响应:

{
    "id": 1,
    "number": "202000",
    "year": 2020,
    "status": "Open",
    "statusDate": 1602298800
 }

按照 StackOverflow 中的建议,我尝试使用以下方法覆盖 ObjectMapper,但没有成功。

@Bean
@Primary
public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {

    ObjectMapper objectMapper = builder.build();

    objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);

    JavaTimeModule javaTimeModule = new JavaTimeModule();
    objectMapper.registerModule(javaTimeModule);
    objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"));

    return objectMapper;
}

【问题讨论】:

  • 禁用SerializationFeature.WRITE_DATES_AS_TIMESTAMPS 就足够了,但可以通过提供全局Jackson 属性来做到这一点。看看Customize the Jackson ObjectMapperWRITE_DATES_AS_TIMESTAMPS 应该默认禁用,但您需要在您的应用程序中检查它。如果JavaTimeModule 在类路径上,Jackson2ObjectMapperBuilder 应该可以找到并识别它,您不必手动注册。

标签: java spring spring-boot jackson spring-restcontroller


【解决方案1】:

Instant.toString() 返回 ISO8601 格式的字符串(就其价值而言)。也许为 Json 字段提供一个 getter 会有所帮助?

【讨论】:

  • 我认为它应该可以工作,但我的意思是我不想改变我所有的 DTO 并依赖它。我想“全局”更改我的 spring 序列化配置。
  • 我已经做了一些事情,比如提供一个具有objectMapper.registerModule(new JavaTimeModule()) 的@Bean ObjectMapper - 我知道这就是你的意思 - 我不知道你在使用时是否会这样做 -案例,但也许这让您知道要搜索什么?像这样:stackoverflow.com/questions/29571587/…
【解决方案2】:

您必须编写一个自定义序列化器和反序列化器类,如下所示:

序列化器类:

public class InstantSerializer extends JsonSerializer<Instant> {

    private DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneOffset.UTC);

    @Override
    public void serialize(Instant instant, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
        String str = dateTimeFormatter.format(instant);

        jsonGenerator.writeString(str);
    }
}

反序列化器类:

public class InstantDeserializer extends JsonDeserializer<Instant> {

    private DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneOffset.UTC);

    @Override
    public Instant deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
        return Instant.from(dateTimeFormatter.parse(jsonParser.getText()));
    }
}

然后在您的 DTO 类中的 Instant 变量顶部添加以下注释,如下所示:

@JsonDeserialize(using = InstantDeserializer.class)
@JsonSerialize(using = InstantSerializer.class)
Instant statusDate;

【讨论】:

  • 我更愿意在 ObjectMapper 本身中配置它,而不是在系统中的每个日期都包含 2 个注释。你认为这可能吗?我发现一些文章解释了我所做的工作,也许是 Spring Boot 版本不匹配。
【解决方案3】:

你有注释吗

@EnableWebMvc

在哪里?

在尝试了一切都没有成功之后,我通过删除我在主类上的 @EnableWebMvc 注释(使用 @SpringBootApplication 注释)来让它工作。

我认为@EnableWebMvc 接管了所有 MVC 配置控制。
如果你真的需要@EnableWebMvc,那么你必须手动注册序列化器/反序列化器。 例如。通过在主类中添加这样的东西(用@SpringBootApplication注释):

  @Override
  public void configureMessageConverters(List<HttpMessageConverter<?>> converters)
  {
    SimpleModule m = new SimpleModule();
    m.addSerializer(Instant.class, new MyCustomJsonSerializer());
    Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder().modules(m);
    converters.add(new MappingJackson2HttpMessageConverter(builder.build()));
  }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-16
    • 1970-01-01
    • 1970-01-01
    • 2022-11-23
    • 2015-08-16
    • 1970-01-01
    相关资源
    最近更新 更多