Tengo un formato de fecha proveniente de API como este:
"start_time": "2015-10-1 3:00 PM GMT+1:00"
Que es AAAA-DD-MM HH: MM am / pm GMT marca de tiempo. Estoy asignando este valor a una variable de fecha en POJO. Obviamente, muestra un error de conversión.
Me gustaría saber 2 cosas:
- ¿Cuál es el formato que necesito usar para llevar a cabo la conversión con Jackson? ¿Date es un buen tipo de campo para esto?
- En general, ¿hay alguna forma de procesar las variables antes de que Jackson las asigne a los miembros de Object? Algo así como, cambiar el formato, cálculos, etc.
Date
clase. java.time, la moderna API de fecha y hora de Java, la reemplazó hace casi 5 años. Úselo y FasterXML / jackson-modules-java8 .Respuestas:
Date
es un buen tipo de campo para esto. Puede hacer que el análisis JSON sea bastante fácil usandoObjectMapper.setDateFormat
:Si. Tiene algunas opciones, incluida la implementación de una costumbre
JsonDeserializer
, por ejemplo, extenderJsonDeserializer<Date>
. Este es un buen comienzo.fuente
LocalDateTime
o enZonedDateTime
lugar deDate
? Dado queDate
está básicamente en desuso (o al menos muchos de sus métodos), me gustaría usar esas alternativas.java.util.Date
explícitamente, quiero señalar que esto no funciona parajava.sql.Date.
Ver también mi respuesta a continuación.Desde Jackson v2.0, puede usar la anotación @JsonFormat directamente en los miembros de Object;
fuente
@JsonFormat(shape=JsonFormat.Shape.STRING, pattern="yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", timezone="GMT")
Por supuesto, hay una forma automatizada llamada serialización y deserialización y puede definirla con anotaciones específicas ( @JsonSerialize , @JsonDeserialize ) como también se menciona en pb2q.
Puede usar java.util.Date y java.util.Calendar ... y probablemente también JodaTime.
Las anotaciones @JsonFormat no funcionaron para mí como quería (ha ajustado la zona horaria a un valor diferente) durante la deserialización (la serialización funcionó a la perfección):
Debe usar el serializador personalizado y el deserializador personalizado en lugar de la anotación @JsonFormat si desea un resultado previsto. He encontrado un muy buen tutorial y solución aquí http://www.baeldung.com/jackson-serialize-dates
Hay ejemplos para los campos de Fecha , pero los necesitaba para los campos de Calendario , así que aquí está mi implementación :
La clase de serializador :
La clase de deserializador :
y el uso de las clases anteriores:
Con esta implementación, la ejecución del proceso de serialización y deserialización da como resultado consecutivamente el valor de origen.
Solo usando la anotación @JsonFormat, la deserialización da un resultado diferente , creo que debido a la configuración predeterminada de la zona horaria interna de la biblioteca, lo que no puede cambiar con los parámetros de anotación (esa fue mi experiencia con la biblioteca Jackson 2.5.3 y la versión 2.6.3 también).
fuente
Solo un ejemplo completo para la aplicación de arranque de primavera con
RFC3339
formato de fecha y horafuente
Para agregar caracteres como T y Z en su fecha
salida
fuente
Trabajando para mi SpringBoot.
salida:
fuente
Sobre la base de la respuesta muy útil de @ miklov-kriven, espero que estos dos puntos adicionales de consideración sean útiles para alguien:
(1) Me parece una buena idea incluir el serializador y el deserializador como clases internas estáticas en la misma clase. NB, utilizando ThreadLocal para la seguridad de subprocesos de SimpleDateFormat.
(2) Como alternativa al uso de las anotaciones @JsonSerialize y @JsonDeserialize en cada miembro individual de la clase, también podría considerar anular la serialización predeterminada de Jackson aplicando la serialización personalizada a nivel de aplicación, es decir, todos los miembros de la clase de tipo Fecha serán serializados por Jackson utilizando esta serialización personalizada sin anotaciones explícitas en cada campo. Si está utilizando Spring Boot, por ejemplo, una forma de hacerlo sería la siguiente:
fuente
Si alguien tiene problemas con el uso de un formato de fecha personalizado para java.sql.Date, esta es la solución más simple:
(Esta respuesta SO me ahorró muchos problemas: https://stackoverflow.com/a/35212795/3149048 )
Jackson usa el SqlDateSerializer de forma predeterminada para java.sql.Date, pero actualmente, este serializador no tiene en cuenta el formato de fecha, vea este problema: https://github.com/FasterXML/jackson-databind/issues/1407 . La solución consiste en registrar un serializador diferente para java.sql.Date como se muestra en el ejemplo de código.
fuente
Quiero señalar que establecer un elemento
SimpleDateFormat
similar al descrito en la otra respuesta solo funciona parajava.util.Date
lo que supongo que se entiende en la pregunta. Pero parajava.sql.Date
el formateador no funciona. En mi caso, no era muy obvio por qué el formateador no funcionaba porque en el modelo que debería ser serializado el campo era de hecho unjava.utl.Date
pero el objeto real terminó siendo unjava.sql.Date
. Esto es posible porqueEntonces esto es realmente válido
Entonces, si se pregunta por qué su campo Fecha no está formateado correctamente, asegúrese de que el objeto sea realmente un
java.util.Date
.Aquí también se menciona por qué
java.sql.Date
no se agregará el manejo .fuente
Date
clases diferentes . Sin embargo, en estos días uno no debería tener ninguno de ellosSimpleDateFormat
. java.time, la API moderna de fecha y hora de Java, los reemplazó hace casi 5 años. Úselo y FasterXML / jackson-modules-java8 .