serialize - Formato JSON Java 8 LocalDateTime en Spring Boot
json to localdate (11)
1) dependencia
compile group: ''com.fasterxml.jackson.datatype'', name: ''jackson-datatype-jsr310'', version: ''2.8.8''
2) Anotación con formato de fecha y hora.
public class RestObject {
private LocalDateTime timestamp;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
public LocalDateTime getTimestamp() {
return timestamp;
}
}
3) Spring Config.
@Configuration
public class JacksonConfig {
@Bean
@Primary
public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
System.out.println("Config is starting.");
ObjectMapper objectMapper = builder.createXmlMapper(false).build();
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
return objectMapper;
}
}
Tengo un pequeño problema con el formato de Java 8 LocalDateTime en mi aplicación Spring Boot. Con las fechas ''normales'' no tengo ningún problema, pero los campos LocalDateTime se convierten a lo siguiente:
"startDate" : {
"year" : 2010,
"month" : "JANUARY",
"dayOfMonth" : 1,
"dayOfWeek" : "FRIDAY",
"dayOfYear" : 1,
"monthValue" : 1,
"hour" : 2,
"minute" : 2,
"second" : 0,
"nano" : 0,
"chronology" : {
"id" : "ISO",
"calendarType" : "iso8601"
}
}
Si bien me gustaría convertirlo en algo como:
"startDate": "2015-01-01"
Mi código se ve así:
@JsonFormat(pattern="yyyy-MM-dd")
@DateTimeFormat(iso = DateTimeFormat.ISO.TIME)
public LocalDateTime getStartDate() {
return startDate;
}
Pero cualquiera de las anotaciones anteriores no funciona, la fecha sigue formateándose como anteriormente. Sugerencias bienvenidas!
Aquí está en maven, con la propiedad para que puedas sobrevivir entre las actualizaciones de arranque de primavera
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>${jackson.version}</version>
</dependency>
Como ya se mencionó, spring-boot obtendrá todo lo que necesita (tanto para web como para webflux starter).
Pero lo que es aún mejor: no necesita registrar ningún módulo usted mismo.
Echa un vistazo
here
.
Dado que
@SpringBootApplication
usa
@EnableAutoConfiguration
debajo del capó, significa que
JacksonAutoConfiguration
se agregará al contexto automáticamente.
Ahora, si miras dentro de
JacksonAutoConfiguration
, verás:
private void configureModules(Jackson2ObjectMapperBuilder builder) {
Collection<Module> moduleBeans = getBeans(this.applicationContext,
Module.class);
builder.modulesToInstall(moduleBeans.toArray(new Module[0]));
}
Este tipo se llamará en el proceso de inicialización y buscará todos los módulos que pueda encontrar en el classpath. (Yo uso Spring Boot 2.1)
Encontré otra solución que puede convertirla al formato que desee y aplicar a todos los tipos de datos LocalDateTime y no tiene que especificar @JsonFormat sobre cada tipo de datos LocalDateTime. primero agregue la dependencia:
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
Agregue el siguiente bean:
@Configuration
public class Java8DateTimeConfiguration {
/**
* Customizing
* http://docs.spring.io/spring-boot/docs/current/reference/html/howto-spring-mvc.html
*
* Defining a @Bean of type Jackson2ObjectMapperBuilder will allow you to customize both default ObjectMapper and XmlMapper (used in MappingJackson2HttpMessageConverter and MappingJackson2XmlHttpMessageConverter respectively).
*/
@Bean
public Module jsonMapperJava8DateTimeModule() {
val bean = new SimpleModule();
bean.addDeserializer (ZonedDateTime.class, new JsonDeserializer<ZonedDateTime>() {
@Override
public ZonedDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
return ZonedDateTime.parse(jsonParser.getValueAsString(), DateTimeFormatter.ISO_ZONED_DATE_TIME);
}
});
bean.addDeserializer(LocalDateTime.class, new JsonDeserializer<LocalDateTime>() {
@Override
public LocalDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
return LocalDateTime.parse(jsonParser.getValueAsString(), DateTimeFormatter.ISO_LOCAL_DATE_TIME);
}
});
bean.addSerializer(ZonedDateTime.class, new JsonSerializer<ZonedDateTime>() {
@Override
public void serialize(
ZonedDateTime zonedDateTime, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
throws IOException {
jsonGenerator.writeString(DateTimeFormatter.ISO_ZONED_DATE_TIME.format(zonedDateTime));
}
});
bean.addSerializer(LocalDateTime.class, new JsonSerializer<LocalDateTime>() {
@Override
public void serialize(
LocalDateTime localDateTime, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
throws IOException {
jsonGenerator.writeString(DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(localDateTime));
}
});
return bean;
}
}
en su archivo de configuración agregue lo siguiente:
@Import(Java8DateTimeConfiguration.class)
Esto serializará y deserializará todas las propiedades LocalDateTime y ZonedDateTime siempre que esté utilizando objectMapper creado por spring.
El formato que obtuvo para ZonedDateTime es: "2017-12-27T08: 55: 17.317 + 02: 00 [Asia / Jerusalem]" para LocalDateTime es: "2017-12-27T09: 05: 30.523"
Escribir esta respuesta también como un recordatorio para mí.
Combiné varias respuestas aquí y al final la mía trabajó con algo como esto. (Estoy usando SpringBoot 1.5.7 y Lombok 1.16.16)
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jdk8</artifactId>
</dependency>
Esto funciona bien:
Agregue la dependencia:
@JsonFormat(pattern="yyyy-MM-dd")
Agrega la anotación:
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
Ahora, debe obtener el formato correcto.
Para usar el mapeador de objetos, necesita registrar JavaTime
@Data
public Class someClass {
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
private LocalDateTime someDate;
}
Estoy usando Springboot 2.0.6 y, por alguna razón, los cambios de la aplicación yml no funcionaron. Y también tenía más requisitos.
¡Intenté crear ObjectMapper y marcarlo como Primario, pero el arranque de primavera se quejó de que ya tengo jacksonObjectMapper marcado como Principal!
Entonces esto es lo que hice. Hice cambios en el mapeador interno.
Mi serializador y deserializador son especiales: tratan con ''dd / MM / AAAA''; y durante la deserialización, hace todo lo posible por usar el formato popular 3-4 para asegurarse de que tengo algo de LocalDate.
@Autowired
ObjectMapper mapper;
@PostConstruct
public ObjectMapper configureMapper() {
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
mapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);
mapper.configure(MapperFeature.ALLOW_COERCION_OF_SCALARS, true);
mapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true);
SimpleModule module = new SimpleModule();
module.addDeserializer(LocalDate.class, new LocalDateDeserializer());
module.addSerializer(LocalDate.class, new LocalDateSerializer());
mapper.registerModule(module);
return mapper;
}
simplemente use:
@JsonFormat(pattern="10/04/2019")
o puede usar el patrón que desee, por ejemplo:
(''-'' in place of ''/'')
@JsonDeserialize(using= LocalDateDeserializer.class)
no funciona para mí con la siguiente dependencia.
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version> 2.9.6</version>
</dependency>
He utilizado el siguiente conversor de código para deserializar la fecha en una fecha
java.sql.Date
.
import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
@SuppressWarnings("UnusedDeclaration")
@Converter(autoApply = true)
public class LocalDateConverter implements AttributeConverter<java.time.LocalDate, java.sql.Date> {
@Override
public java.sql.Date convertToDatabaseColumn(java.time.LocalDate attribute) {
return attribute == null ? null : java.sql.Date.valueOf(attribute);
}
@Override
public java.time.LocalDate convertToEntityAttribute(java.sql.Date dbData) {
return dbData == null ? null : dbData.toLocalDate();
}
}
Agregué la dependencia com.fasterxml.jackson.datatype: jackson-datatype-jsr310: 2.6.1 y comencé a obtener la fecha en el siguiente formato:
"birthDate": [
2016,
1,
25,
21,
34,
55
]
que no es lo que quería pero me estaba acercando. Luego agregué lo siguiente
spring.jackson.serialization.write_dates_as_timestamps=false
al archivo application.properties que me dio el formato correcto que necesitaba.
"birthDate": "2016-01-25T21:34:55"
actualización : Spring Boot 2.x ya no requiere esta configuración. He escrito una respuesta más actualizada aquí .
(Esta es la forma de hacerlo antes de Spring Boot 2.x, podría ser útil para las personas que trabajan en una versión anterior de Spring Boot)
Finalmente encontré here cómo hacerlo. Para solucionarlo, necesitaba otra dependencia:
compile("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.4.0")
Al incluir esta dependencia, Spring registrará automáticamente un convertidor, como se describe here . Después de eso, debe agregar lo siguiente a application.properties:
spring.jackson.serialization.write_dates_as_timestamps=false
Esto asegurará que se utilice un convertidor correcto y las fechas se imprimirán en el formato
2016-03-16T13:56:39.492
Las anotaciones solo son necesarias en caso de que desee cambiar el formato de fecha.