序列化/反序列化java 8jacksonJSON映射器的java.time

如何在Java 8 LocalDateTime中使用Jackson JSON映射器?

org.codehaus.jackson.map.JsonMappingException:无法从JSONstring实例化[simple type,class java.time.LocalDateTime]types的值; 没有单个string构造函数/工厂方法(通过引用链:MyDTO [“field1”] – > SubDTO [“date”])

这里不需要使用自定义序列化器/反序列化器。 使用jackson-modules-java8的date时间模块 :

数据types模块,使jackson认识到Java 8date和时间API数据types(JSR-310)。

这个模块增加了对很多类的支持:

  • 持续时间
  • 瞬间
  • LocalDateTime
  • LOCALDATE的
  • 当地时间
  • 月日
  • OffsetDateTime
  • OffsetTime
  • YearMonth
  • ZonedDateTime
  • 了zoneid
  • ZoneOffset

告诉jackson使用你自定义的[de]序列化类来映射:

 @JsonSerialize(using = LocalDateTimeSerializer.class) @JsonDeserialize(using = LocalDateTimeDeserializer.class) private LocalDateTime ignoreUntil; 

提供自定义类:

 public class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime> { @Override public void serialize(LocalDateTime arg0, JsonGenerator arg1, SerializerProvider arg2) throws IOException, JsonProcessingException { arg1.writeString(arg0.toString()); } } public class LocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> { @Override public LocalDateTime deserialize(JsonParser arg0, DeserializationContext arg1) throws IOException, JsonProcessingException { return LocalDateTime.parse(arg0.getText()); } } 

随机事实:如果我嵌套上面的类,而不是使他们静态,错误消息是奇怪的: org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/json;charset=UTF-8' not supported

这个maven依赖将解决你的问题:

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

有一件事我挣扎着,就是ZonedDateTime时区在反序列化的时候变成了GMT。 原来,默认情况下,jackson将其replace为上下文中的一个。要使区域一必须禁用此“function”

 Jackson2ObjectMapperBuilder.json() .featuresToDisable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE) 

如果您使用的是fastxml的ObjectMapper类,那么默认情况下ObjectMapper不会理解LocalDateTime类,所以您需要在gradle / maven中添加另一个依赖项:

 compile 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.7.3' 

现在你需要把这个库提供的数据types支持注册到你的objectmapper对象中,这可以通过以下方法来完成:

 ObjectMapper objectMapper = new ObjectMapper(); objectMapper.findAndRegisterModules(); 

现在,在你的jsonString中,你可以很容易地把你的java.LocalDateTime字段如下所示:

 { "user_id": 1, "score": 9, "date_time": "2016-05-28T17:39:44.937" } 

通过这样做,你的Json文件到Java对象的转换就可以正常工作了,你可以通过以下方式读取文件:

 objectMapper.readValue(jsonString, new TypeReference<List<User>>() { }); 

在使用Spring引导时,我遇到了类似的问题。 与春季启动1.5.1.RELEASE我所要做的就是添加依赖关系:

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

如果您使用的是Jersey,那么您需要像其他人一样添加Maven依赖项(jackson-datatype-jsr310),并注册您的对象映射器实例,如下所示:

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

在您的资源中注册Jackson时,您需要像这样添加此映射器:

 final ResourceConfig rc = new ResourceConfig().packages("<your package>"); rc .register(JacksonObjectMapper.class) .register(JacksonJaxbJsonProvider.class); 

如果因为某些原因无法使用jackson-modules-java8,那么只要使用@JsonIgnore和@JsonGetter&@JsonSetter就可以(反序列化)即时字段:

 public class MyBean { private Instant time = Instant.now(); @JsonIgnore public Instant getTime() { return this.time; } public void setTime(Instant time) { this.time = time; } @JsonGetter private long getEpochTime() { return this.time.toEpochMilli(); } @JsonSetter private void setEpochTime(long time) { this.time = Instant.ofEpochMilli(time); } } 

例:

 @Test public void testJsonTime() throws Exception { String json = new ObjectMapper().writeValueAsString(new MyBean()); System.out.println(json); MyBean myBean = new ObjectMapper().readValue(json, MyBean.class); System.out.println(myBean.getTime()); } 

产量

 {"epochTime":1506432517242} 2017-09-26T13:28:37.242Z