java - pattern - ¿Cómo serializar Joda DateTime con el procesador Jackson JSON?
send date json java (9)
¿Cómo hago para que Jackson serialice mi objeto Joda DateTime según un patrón simple (como "dd-MM-aaaa")?
He intentado:
@JsonSerialize(using=DateTimeSerializer.class)
private final DateTime date;
También lo intenté:
ObjectMapper mapper = new ObjectMapper()
.getSerializationConfig()
.setDateFormat(df);
¡Gracias!
la solución fácil
He encontrado un problema similar y mi solución es mucho más clara que la anterior.
Simplemente utilicé el patrón en la anotación @JSonFormat
Básicamente, mi clase tiene un campo DateTime
, así que puse una anotación alrededor del getter:
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
public DateTime getDate() {
return date;
}
Serializo la clase con ObjectMapper
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JodaModule());
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
ObjectWriter ow = mapper.writer();
try {
String logStr = ow.writeValueAsString(log);
outLogger.info(logStr);
} catch (IOException e) {
logger.warn("JSON maping exception", e);
}
Usamos Jackson 2.5.4
Como dijo @Kimble, con Jackson 2, usar el formato predeterminado es muy fácil; simplemente registre JodaModule
en su ObjectMapper
.
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JodaModule());
Para la serialización / StdScalarSerializer
personalizada de DateTime
, debe implementar su propio StdScalarSerializer
y StdScalarDeserializer
; es bastante intrincado, pero de todos modos.
Por ejemplo, aquí hay un serializador DateTime
que usa el ISODateFormat
con la zona horaria UTC:
public class DateTimeSerializer extends StdScalarSerializer<DateTime> {
public DateTimeSerializer() {
super(DateTime.class);
}
@Override
public void serialize(DateTime dateTime,
JsonGenerator jsonGenerator,
SerializerProvider provider) throws IOException, JsonGenerationException {
String dateTimeAsString = ISODateTimeFormat.withZoneUTC().print(dateTime);
jsonGenerator.writeString(dateTimeAsString);
}
}
Y el deserializador correspondiente:
public class DateTimeDesrializer extends StdScalarDeserializer<DateTime> {
public DateTimeDesrializer() {
super(DateTime.class);
}
@Override
public DateTime deserialize(JsonParser jsonParser,
DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
try {
JsonToken currentToken = jsonParser.getCurrentToken();
if (currentToken == JsonToken.VALUE_STRING) {
String dateTimeAsString = jsonParser.getText().trim();
return ISODateTimeFormat.withZoneUTC().parseDateTime(dateTimeAsString);
}
} finally {
throw deserializationContext.mappingException(getValueClass());
}
}
Luego une esto con un módulo:
public class DateTimeModule extends SimpleModule {
public DateTimeModule() {
super();
addSerializer(DateTime.class, new DateTimeSerializer());
addDeserializer(DateTime.class, new DateTimeDeserializer());
}
}
Luego registre el módulo en su ObjectMapper
:
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new DateTimeModule());
En el objeto que está mapeando:
@JsonSerialize(using = CustomDateSerializer.class)
public DateTime getDate() { ... }
En CustomDateSerializer:
public class CustomDateSerializer extends JsonSerializer<DateTime> {
private static DateTimeFormatter formatter =
DateTimeFormat.forPattern("dd-MM-yyyy");
@Override
public void serialize(DateTime value, JsonGenerator gen,
SerializerProvider arg2)
throws IOException, JsonProcessingException {
gen.writeString(formatter.print(value));
}
}
Esto se ha vuelto muy fácil con Jackson 2.0 y el módulo Joda.
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JodaModule());
Dependencia de Maven:
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-joda</artifactId>
<version>2.1.1</version>
</dependency>
Código y documentación: https://github.com/FasterXML/jackson-datatype-joda
Binarios: http://repo1.maven.org/maven2/com/fasterxml/jackson/datatype/jackson-datatype-joda/
Estoy usando Java 8 y esto funcionó para mí:
agregue la dependencia en pom.xml
<dependency> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-jsr310</artifactId> <version>2.4.0</version> </dependency>
y agrega JodaModule en tu ObjectMapper
ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new JodaModule());
Mientras tanto, Jackson registra el módulo Joda automáticamente cuando el JodaModule está en classpath. Acabo de agregar jackson-datatype-joda a Maven y funcionó al instante.
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-joda</artifactId>
<version>2.8.7</version>
</dependency>
Salida JSON:
{"created" : "2017-03-28T05:59:27.258Z"}
Para aquellos con Spring Boot, tienes que agregar el módulo a tu contexto y se agregará a tu configuración de esta manera.
@Bean
public Module jodaTimeModule() {
return new JodaModule();
}
Y si quiere usar el nuevo módulo de tiempo java8 jsr-310.
@Bean
public Module jodaTimeModule() {
return new JavaTimeModule();
}
Parece que para Jackson 1.9.12 no existe tal posibilidad por defecto, debido a:
public final static class DateTimeSerializer
extends JodaSerializer<DateTime>
{
public DateTimeSerializer() { super(DateTime.class); }
@Override
public void serialize(DateTime value, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonGenerationException
{
if (provider.isEnabled(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS)) {
jgen.writeNumber(value.getMillis());
} else {
jgen.writeString(value.toString());
}
}
@Override
public JsonNode getSchema(SerializerProvider provider, java.lang.reflect.Type typeHint)
{
return createSchemaNode(provider.isEnabled(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS)
? "number" : "string", true);
}
}
Esta clase serializa datos usando el método toString () de Joda DateTime.
El enfoque propuesto por Rusty Kuntz funciona perfecto para mi caso.
https://.com/a/10835114/1113510
Aunque puede poner una anotación para cada campo de fecha, es mejor hacer una configuración global para su asignador de objetos. Si usa jackson, puede configurar su muelle de la siguiente manera:
<bean id="jacksonObjectMapper" class="com.company.CustomObjectMapper" />
<bean id="jacksonSerializationConfig" class="org.codehaus.jackson.map.SerializationConfig"
factory-bean="jacksonObjectMapper" factory-method="getSerializationConfig" >
</bean>
Para CustomObjectMapper:
public class CustomObjectMapper extends ObjectMapper {
public CustomObjectMapper() {
super();
configure(Feature.WRITE_DATES_AS_TIMESTAMPS, false);
setDateFormat(new SimpleDateFormat("EEE MMM dd yyyy HH:mm:ss ''GMT''ZZZ (z)"));
}
}
Por supuesto, SimpleDateFormat puede usar cualquier formato que necesite.