Como serializar Joda DateTime com Jackson JSON processer?

Como faço para Jackson serializar meu object Joda DateTime de acordo com um padrão simples (como “dd-MM-yyyy”)?

Eu tentei:

@JsonSerialize(using=DateTimeSerializer.class) private final DateTime date; 

Eu também tentei:

 ObjectMapper mapper = new ObjectMapper() .getSerializationConfig() .setDateFormat(df); 

Obrigado!

Isso se tornou muito fácil com o Jackson 2.0 e o módulo Joda.

 ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new JodaModule()); 

Dependência Maven:

  com.fasterxml.jackson.datatype jackson-datatype-joda 2.1.1  

Código e documentação: https://github.com/FasterXML/jackson-datatype-joda

Binários: http://repo1.maven.org/maven2/com/fasterxml/jackson/datatype/jackson-datatype-joda/

No object que você está mapeando:

 @JsonSerialize(using = CustomDateSerializer.class) public DateTime getDate() { ... } 

Em CustomDateSerializer:

 public class CustomDateSerializer extends JsonSerializer { 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)); } } 

Como o @Kimble disse, com Jackson 2, usar a formatação padrão é muito fácil; Basta registrar o JodaModule no seu ObjectMapper .

 ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new JodaModule()); 

Para serialização / desserialização personalizada de DateTime , você precisa implementar seu próprio StdScalarSerializer e StdScalarDeserializer ; é muito complicado, mas de qualquer maneira.

Por exemplo, aqui está um serializador DateTime que usa o ISODateFormat com o fuso horário UTC:

 public class DateTimeSerializer extends StdScalarSerializer { 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); } } 

E o desserializador correspondente:

 public class DateTimeDesrializer extends StdScalarDeserializer { 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()); } } 

Em seguida, amarre-os junto com um módulo:

 public class DateTimeModule extends SimpleModule { public DateTimeModule() { super(); addSerializer(DateTime.class, new DateTimeSerializer()); addDeserializer(DateTime.class, new DateTimeDeserializer()); } } 

Então registre o módulo no seu ObjectMapper :

 ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new DateTimeModule()); 

https://stackoverflow.com/a/10835114/1113510

Embora você possa colocar uma anotação para cada campo de data, é melhor fazer uma configuração global para o mapeador de objects. Se você usa jackson você pode configurar sua mola como segue:

    

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

Claro, SimpleDateFormat pode usar qualquer formato que você precisa.

a solução fácil

Eu encontrei um problema semelhante e minha solução é muito clara do que acima.

Eu simplesmente usei o padrão na anotação @JSonFormat

Basicamente minha class tem um campo DateTime , então coloco uma anotação em torno do getter:

 @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") public DateTime getDate() { return date; } 

Serializo a class com o 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); } 

Nós usamos Jackson 2.5.4

Enquanto isso, Jackson registra o módulo Joda automaticamente quando o JodaModule está no classpath. Acabei de adicionar o jackson-datatype-joda ao Maven e funcionou instantaneamente.

  com.fasterxml.jackson.datatype jackson-datatype-joda 2.8.7  

Saída JSON:

 {"created" : "2017-03-28T05:59:27.258Z"} 

Parece que para Jackson 1.9.12 não existe essa possibilidade por padrão, devido a:

 public final static class DateTimeSerializer extends JodaSerializer { 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 class serializa os dados usando o método toString () do Joda DateTime.

Abordagem proposta por Rusty Kuntz funciona perfeito para o meu caso.

Para aqueles com Spring Boot você tem que adicionar o módulo ao seu contexto e ele será adicionado à sua configuração como este.

 @Bean public Module jodaTimeModule() { return new JodaModule(); } 

E se você quiser usar o novo módulo de tempo java8 jsr-310.

 @Bean public Module jodaTimeModule() { return new JavaTimeModule(); } 

Estou usando o Java 8 e isso funcionou para mim:

adicione a dependência em pom.xml
com.fasterxml.jackson.datatype jackson-datatype-jsr310 2.4.0

e adicione o JodaModule no seu ObjectMapper
ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new JodaModule());