type parse not localdatetime from exist error deserialize datatype creators cannot jackson java-time

jackson - parse - localdate serializer



serializar/deserializar java 8 java.time con el mapeador Jackson JSON (14)

¿Cómo uso el mapeador Jackson JSON con Java 8 LocalDateTime?

org.codehaus.jackson.map.JsonMappingException: no se puede crear una instancia del valor de tipo [tipo simple, clase java.time.LocalDateTime] de la cadena JSON; sin constructor de cadena única / método de fábrica (a través de la cadena de referencia: MyDTO ["field1"] -> SubDTO ["date"])


Actualización: Dejando esta respuesta por razones históricas, pero no la recomiendo. Por favor vea la respuesta aceptada arriba.

Dígale a Jackson que asigne usando sus clases de serialización [de] personalizadas:

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

proporcionar clases personalizadas:

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

hecho aleatorio: si org.springframework.web.HttpMediaTypeNotSupportedException: Content type ''application/json;charset=UTF-8'' not supported clases anteriores y no las hago estáticas, el mensaje de error es extraño: org.springframework.web.HttpMediaTypeNotSupportedException: Content type ''application/json;charset=UTF-8'' not supported


Esta dependencia de Maven resolverá su problema:

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

Una cosa que me ha costado es que la zona horaria ZonedDateTime se cambie a GMT durante la deserialización. Resultó que, por defecto, Jackson lo reemplaza con uno del contexto. Para mantener la zona, uno debe deshabilitar esta ''característica''

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


Este es solo un ejemplo de cómo usarlo en una prueba unitaria que pirateé para depurar este problema. Los ingredientes clave son

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

Código:

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



Para aquellos que usan Spring Boot 2.x

No es necesario hacer nada de lo anterior: Java 8 LocalDateTime está serializado / deserializado de fábrica. Tuve que hacer todo lo anterior en 1.x, pero con Boot 2.x, funciona a la perfección.

Consulte también esta referencia JSON Java 8 LocalDateTime format en Spring Boot


Puede configurar esto en su archivo application.yml para resolver la hora instantánea, que es la API de fecha en java8:

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


Si alguien tiene problemas al usar SpringBoot aquí es cómo solucioné el problema sin agregar una nueva dependencia.

En la Spring 2.1.3 Jackson espera que la cadena de fecha 2019-05-21T07:37:11.000 en este formato yyyy-MM-dd HH:mm:ss.SSS des- LocalDateTime en LocalDateTime . Asegúrese de que la cadena de fecha separe la fecha y la hora con T no con el space . segundos ( ss ) y milisegundos ( SSS ) podrían omitirse.

@JsonProperty("last_charge_date") public LocalDateTime lastChargeDate;


Si considera usar fastjson, puede resolver su problema, tenga en cuenta la versión

<dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.56</version> </dependency>


Si está utilizando Jersey, entonces necesita agregar la dependencia Maven (jackson-datatype-jsr310) como lo sugirieron los demás y registrar su instancia de mapeador de objetos de la siguiente manera:

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

Al registrar a Jackson en sus recursos, debe agregar este mapeador de la siguiente manera:

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


Si está utilizando Spring Boot y tiene este problema con el OffsetDateTime, entonces necesita usar el registerModules como respondió anteriormente @greperror (respondió el 28 de mayo de 16 a las 13:04) pero tenga en cuenta que hay una diferencia. La dependencia mencionada no necesita ser agregada ya que supongo que Spring Boot ya la tiene. Estaba teniendo este problema con Spring boot y funcionó para mí sin agregar esta dependencia.


Si está utilizando la clase ObjectMapper de rapidxml, por defecto ObjectMapper no entiende la clase LocalDateTime, por lo tanto, debe agregar otra dependencia en su gradle / maven:

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

Ahora debe registrar el soporte de tipo de datos que ofrece esta biblioteca en su objeto objectmapper, esto se puede hacer de la siguiente manera:

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

Ahora, en su jsonString, puede poner fácilmente su campo java.LocalDateTime de la siguiente manera:

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

Al hacer todo esto, su conversión de archivo Json a objeto Java funcionará bien, puede leer el archivo de la siguiente manera:

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


Si no puede usar jackson-modules-java8 por cualquier razón, puede (des) serializar el campo instantáneo long use @JsonIgnore y @JsonGetter y @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); } }

Ejemplo:

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

rendimientos

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


Tuve un problema similar al usar Spring Boot . Con Spring boot 1.5.1.RELEASE todo lo que tuve que hacer es agregar dependencia:

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


Utilizo este formato de hora: "{birthDate": "2018-05-24T13:56:13Z}" para deserializar de json a java.time.Instant (ver captura de pantalla)