简体   繁体   中英

Convert Instant to ISO8601 date format not working in Spring Boot

I'm using spring boot 2.3.4.RELEASE and when trying to convert a DTO containing an Instant attribute to JSON format, the jackson ObjectMapper keeps converting it to timestamp format, even with write-dates-as-timestamps option turned off.

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;
}

Rest Controller response:

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

Following recommendations found here in StackOverflow, I tried to override the ObjectMapper using the follwoing approach, but it didn't work.

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

Instant.toString() returns the ISO8601 formatted string (for what its worth). Perhaps providing a getter for the Json field would help?

You have to write a Custom Serializer and De Serializer classes as below:

Serializer Class:

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

Deserializer Class:

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

Then add the below annotations on top of the Instant variable in your DTO class as below:

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

Do you have annotation

@EnableWebMvc

anywhere?

After having tried everything without success, I got it to work by removing the @EnableWebMvc annotation I had on the main class (annotated with @SpringBootApplication).

I think @EnableWebMvc takes over all MVC configuration control.
If you really need @EnableWebMvc, then you have to register the serializer / deserializer by hand. Eg. by adding something like this to the main class (annotated with @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()));
  }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM