Jackson serializes a ZonedDateTime wrongly in Spring Boot

前端 未结 4 1841
有刺的猬
有刺的猬 2021-02-05 01:28

I have a simple application with Spring Boot and Jetty. I have a simple controller returning an object which has a Java 8 ZonedDateTime:

public clas         


        
相关标签:
4条回答
  • 2021-02-05 02:06

    If you either don't rely on SpringBoot's auto-configuration feature - you don't provide spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS = false property into your configuration file - or for whatever reason you create ObjectMapper instance manually. You can disable this feature programatically as follows:

    ObjectMapper m = new ObjectMapper();
    m.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
    

    this is for jackson 2.8.7

    0 讨论(0)
  • 2021-02-05 02:10

    For Jackson 2.10 and above,

    parent pom.xml

    <!-- https://github.com/FasterXML/jackson-bom -->
    <dependencyManagement>
      <dependency>
        <groupId>com.fasterxml.jackson</groupId>
        <artifactId>jackson-bom</artifactId>
        <version>2.10.3</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencyManagement>
    

    module pom.xml

    <!-- https://github.com/FasterXML/jackson-modules-java8 -->
    <dependency>
        <groupId>com.fasterxml.jackson.datatype</groupId>
        <artifactId>jackson-datatype-jsr310</artifactId>
    </dependency>
    

    JsonMapper creation, possibly in your @Configuration class

    @Bean
    public JsonMapper jsonMapper() {
        return JsonMapper.builder()
            .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
            .addModule(new JavaTimeModule())
            .build();
    }
    

    Further reading:

    • What's new in Jackson 2.10
    • Use JsonMapper instead of ObjectMapper
    • Use Builder pattern
    0 讨论(0)
  • 2021-02-05 02:13

    There is a library jackson-datatype-jsr310. Try it.

    This library covers new datetime API and includes serializers for ZonedDateTime too.

    All you need is just to add JavaTimeModule:

    ObjectMapper mapper = new ObjectMapper();
    mapper.registerModule(new JavaTimeModule());
    

    UPDATE

    To convert datetime to ISO-8601 string you should disable WRITE_DATES_AS_TIMESTAMPS feature. You can easily do by either overriding ObjectMapper bean or by using application properties:

    spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS = false
    
    0 讨论(0)
  • 2021-02-05 02:20

    The answer was already mentioned above but I think it's missing some info. For those looking to parse Java 8 timestamps in many forms (not just ZonedDateTime). You need a recent version of jackson-datatype-jsr310 in your POM and have the following module registered:

    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.registerModule(new JavaTimeModule());
    objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
    

    To test this code

    @Test
    void testSeliarization() throws IOException {
        String expectedJson = "{\"parseDate\":\"2018-12-04T18:47:38.927Z\"}";
        MyPojo pojo = new MyPojo(ZonedDateTime.parse("2018-12-04T18:47:38.927Z"));
    
        // serialization
        assertThat(objectMapper.writeValueAsString(pojo)).isEqualTo(expectedJson);
    
        // deserialization
        assertThat(objectMapper.readValue(expectedJson, MyPojo.class)).isEqualTo(pojo);
    }
    

    Note that you can configure your object mapper globally in Spring or dropwizard to achieve this. I have not yet found a clean way to do this as an annotation on a field without registering a custom (de)serializer.

    0 讨论(0)
提交回复
热议问题