Formato Java 8 LocalDate Jackson

Per java.util.Date quando lo faccio

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd/MM/yyyy") private Date dateOfBirth; 

quindi nella richiesta JSON quando invio

 { {"dateOfBirth":"01/01/2000"} } 

Funziona.

Come dovrei farlo per il campo LocalDate di Java 8 ??

Ho provato ad averlo

 @JsonDeserialize(using = LocalDateDeserializer.class) @JsonSerialize(using = LocalDateSerializer.class) private LocalDate dateOfBirth; 

Non ha funzionato.

Qualcuno può farmi sapere qual è il modo giusto per farlo?

Di seguito sono le dipendenze

  org.jboss.resteasy jaxrs-api 3.0.9.Final   com.fasterxml.jackson.jaxrs jackson-jaxrs-json-provider 2.4.2   com.wordnik swagger-annotations 1.3.10   

Non sono mai stato in grado di farlo funzionare con le annotazioni. Per farlo funzionare, ho creato un ContextResolver per ObjectMapper , poi ho aggiunto il JSR310Module , insieme a un altro avvertimento, che era la necessità di impostare write-date-as-timestamp su false. Vedi di più nella documentazione del modulo JSR310 . Ecco un esempio di ciò che ho usato.

Dipendenza

  com.fasterxml.jackson.datatype jackson-datatype-jsr310 2.4.0  

Nota: un problema che ho dovuto affrontare è che la versione di jackson-annotation jsr310 da un’altra dipendenza, ha utilizzato la versione 2.3.2, che ha annullato il 2.4 richiesto da jsr310 . Quello che è successo è che ho ottenuto un NoClassDefFound per ObjectIdResolver , che è una class 2.4. Quindi avevo solo bisogno di allineare le versioni di dipendenza incluse

ContextResolver

 import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.datatype.jsr310.JSR310Module; import javax.ws.rs.ext.ContextResolver; import javax.ws.rs.ext.Provider; @Provider public class ObjectMapperContextResolver implements ContextResolver { private final ObjectMapper MAPPER; public ObjectMapperContextResolver() { MAPPER = new ObjectMapper(); MAPPER.registerModule(new JSR310Module()); MAPPER.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); } @Override public ObjectMapper getContext(Class type) { return MAPPER; } } 

Classe di risorse

 @Path("person") public class LocalDateResource { @GET @Produces(MediaType.APPLICATION_JSON) public Response getPerson() { Person person = new Person(); person.birthDate = LocalDate.now(); return Response.ok(person).build(); } @POST @Consumes(MediaType.APPLICATION_JSON) public Response createPerson(Person person) { return Response.ok( DateTimeFormatter.ISO_DATE.format(person.birthDate)).build(); } public static class Person { public LocalDate birthDate; } } 

Test

curl -v http://localhost:8080/api/person
Risultato: {"birthDate":"2015-03-01"}

curl -v -POST -H "Content-Type:application/json" -d "{\"birthDate\":\"2015-03-01\"}" http://localhost:8080/api/person
Risultato: 2015-03-01


Vedi anche qui per la soluzione JAXB.

AGGIORNARE

Il JSR310Module è deprecato dalla versione 2.7 di Jackson. Invece, dovresti registrare il modulo JavaTimeModule . È sempre la stessa dipendenza.

@JsonSerialize e @JsonDeserialize hanno funzionato bene per me. Eliminano la necessità di importare il modulo aggiuntivo jsr310:

 @JsonDeserialize(using = LocalDateDeserializer.class) @JsonSerialize(using = LocalDateSerializer.class) private LocalDate dateOfBirth; 

deserializzatore:

 public class LocalDateDeserializer extends StdDeserializer { private static final long serialVersionUID = 1L; protected LocalDateDeserializer() { super(LocalDate.class); } @Override public LocalDate deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { return LocalDate.parse(jp.readValueAs(String.class)); } } 

Serializer:

 public class LocalDateSerializer extends StdSerializer { private static final long serialVersionUID = 1L; public LocalDateSerializer(){ super(LocalDate.class); } @Override public void serialize(LocalDate value, JsonGenerator gen, SerializerProvider sp) throws IOException, JsonProcessingException { gen.writeString(value.format(DateTimeFormatter.ISO_LOCAL_DATE)); } } 

In spring web app di avvio, con “jackson” e “jsr310” versione “2.8.5”

 compile "com.fasterxml.jackson.core:jackson-databind:2.8.5" runtime "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.8.5" 

Il ‘@JsonFormat’ funziona:

 import com.fasterxml.jackson.annotation.JsonFormat; @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd") private LocalDate birthDate; 
  ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new JavaTimeModule()); mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); 

funziona bene per me

Solo un aggiornamento della risposta di Christopher.

Dalla versione 2.6.0

  com.fasterxml.jackson.datatype jackson-datatype-jsr310 2.9.0  

Utilizzare JavaTimeModule anziché JSR310Module (obsoleto).

 @Provider public class ObjectMapperContextResolver implements ContextResolver { private final ObjectMapper MAPPER; public ObjectMapperContextResolver() { MAPPER = new ObjectMapper(); MAPPER.registerModule(new JavaTimeModule()); MAPPER.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); } @Override public ObjectMapper getContext(Class type) { return MAPPER; } } 

Secondo la documentazione , il nuovo JavaTimeModule utilizza le stesse impostazioni standard per la serializzazione predefinita che NON utilizza Id di fuso orario e utilizza solo offset di fuso orario conformi allo standard ISO-8601.

Il comportamento può essere modificato utilizzando SerializationFeature.WRITE_DATES_WITH_ZONE_ID

Dato che LocalDateSerializer trasforma int “[anno, mese, giorno]” (un array json) anziché “anno-mese-giorno” (una stringa json) per impostazione predefinita, e dal momento che non voglio richiedere alcuna configurazione speciale di ObjectMapper ( puoi fare in modo che LocalDateSerializer generi stringhe se disabiliti SerializationFeature.WRITE_DATES_AS_TIMESTAMPS ma ciò richiede un’ulteriore configurazione al tuo ObjectMapper ), io uso il seguente:

importazioni:

 import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer; 

codice:

 // generates "yyyy-MM-dd" output @JsonSerialize(using = ToStringSerializer.class) // handles "yyyy-MM-dd" input just fine @JsonDeserialize(using = LocalDateDeserializer.class) private LocalDate localDate; 

E ora posso solo usare il new ObjectMapper() per leggere e scrivere i miei oggetti senza alcuna configurazione speciale.