serialize/deserialize java 8 java.time with Jackson JSON mapper

后端 未结 17 1138
隐瞒了意图╮
隐瞒了意图╮ 2020-11-22 15:56

How do I use Jackson JSON mapper with Java 8 LocalDateTime?

org.codehaus.jackson.map.JsonMappingException: Can not instantiate value of type [simple t

相关标签:
17条回答
  • 2020-11-22 16:31

    If you are using Jersey then you need to add the Maven dependency (jackson-datatype-jsr310) as the others suggested and register your object mapper instance like so:

    @Provider
    public class JacksonObjectMapper implements ContextResolver<ObjectMapper> {
    
      final ObjectMapper defaultObjectMapper;
    
      public JacksonObjectMapper() {
        defaultObjectMapper = createDefaultMapper();
      }
    
      @Override
      public ObjectMapper getContext(Class<?> type) {
        return defaultObjectMapper;
      }
    
      private static ObjectMapper createDefaultMapper() {
        final ObjectMapper mapper = new ObjectMapper();    
        mapper.registerModule(new JavaTimeModule());
        return mapper;
      }
    }
    

    When registering Jackson in your resources, you need to add this mapper like so:

    final ResourceConfig rc = new ResourceConfig().packages("<your package>");
    rc
      .register(JacksonObjectMapper.class)
      .register(JacksonJaxbJsonProvider.class);
    
    0 讨论(0)
  • 2020-11-22 16:34

    all you need to know is in Jackson Documentation https://www.baeldung.com/jackson-serialize-dates

    Ad.9 quick solved the problem for me.

    ObjectMapper mapper = new ObjectMapper();
    mapper.registerModule(new JavaTimeModule());
    mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
    
    0 讨论(0)
  • 2020-11-22 16:35

    This maven dependency will solve your problem:

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

    One thing I've struggled is that for ZonedDateTime timezone being changed to GMT during deserialization. Turned out, that by default jackson replaces it with one from context.. To keep zone one must disable this 'feature'

    Jackson2ObjectMapperBuilder.json()
        .featuresToDisable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE)
    
    0 讨论(0)
  • 2020-11-22 16:36

    This is just an example how to use it in a unit test that I hacked to debug this issue. The key ingredients are

    • mapper.registerModule(new JavaTimeModule());
    • maven dependency of <artifactId>jackson-datatype-jsr310</artifactId>

    Code:

    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
    import org.testng.Assert;
    import org.testng.annotations.Test;
    
    import java.io.IOException;
    import java.io.Serializable;
    import java.time.Instant;
    
    class Mumu implements Serializable {
        private Instant from;
        private String text;
    
        Mumu(Instant from, String text) {
            this.from = from;
            this.text = text;
        }
    
        public Mumu() {
        }
    
        public Instant getFrom() {
            return from;
        }
    
        public String getText() {
            return text;
        }
    
        @Override
        public String toString() {
            return "Mumu{" +
                    "from=" + from +
                    ", text='" + text + '\'' +
                    '}';
        }
    }
    public class Scratch {
    
    
        @Test
        public void JacksonInstant() throws IOException {
            ObjectMapper mapper = new ObjectMapper();
            mapper.registerModule(new JavaTimeModule());
    
            Mumu before = new Mumu(Instant.now(), "before");
            String jsonInString = mapper.writeValueAsString(before);
    
    
            System.out.println("-- BEFORE --");
            System.out.println(before);
            System.out.println(jsonInString);
    
            Mumu after = mapper.readValue(jsonInString, Mumu.class);
            System.out.println("-- AFTER --");
            System.out.println(after);
    
            Assert.assertEquals(after.toString(), before.toString());
        }
    
    }
    
    0 讨论(0)
  • 2020-11-22 16:37

    I use this time format: "{birthDate": "2018-05-24T13:56:13Z}" to deserialize from json into java.time.Instant (see screenshot)

    0 讨论(0)
  • 2020-11-22 16:38

    You may set this in your application.yml file to resolve Instant time, which is Date API in java8:

    spring.jackson.serialization.write-dates-as-timestamps=false
    
    0 讨论(0)
提交回复
热议问题