Ich war nie in der Lage, dies mithilfe von Anmerkungen einfach zum Laufen zu bringen. Damit es funktioniert, habe ich ein ContextResolver
for erstellt ObjectMapper
und dann das JSR310Module
( Update: jetzt ist es JavaTimeModule
stattdessen ) hinzugefügt , zusammen mit einer weiteren Einschränkung, bei der das Schreibdatum als Zeitstempel auf false gesetzt werden musste. Weitere Informationen finden Sie in der Dokumentation zum JSR310-Modul . Hier ist ein Beispiel für das, was ich verwendet habe.
Abhängigkeit
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.4.0</version>
</dependency>
Hinweis: Ein Problem, mit dem ich konfrontiert war, ist, dass die jackson-annotation
Version, die von einer anderen Abhängigkeit abgerufen wurde, Version 2.3.2 verwendete, die die von der jsr310
. Was passiert ist, war, dass ich ein NoClassDefFound für ObjectIdResolver
eine 2.4-Klasse bekommen habe. Also musste ich nur die enthaltenen Abhängigkeitsversionen ausrichten
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<ObjectMapper> {
private final ObjectMapper MAPPER;
public ObjectMapperContextResolver() {
MAPPER = new ObjectMapper();
// Now you should use JavaTimeModule instead
MAPPER.registerModule(new JSR310Module());
MAPPER.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
}
@Override
public ObjectMapper getContext(Class<?> type) {
return MAPPER;
}
}
Ressourcenklasse
@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;
}
}
Prüfung
curl -v http://localhost:8080/api/person
Ergebnis: {"birthDate":"2015-03-01"}
curl -v -POST -H "Content-Type:application/json" -d "{\"birthDate\":\"2015-03-01\"}" http://localhost:8080/api/person
Ergebnis: 2015-03-01
Siehe auch hier für die JAXB-Lösung.
AKTUALISIEREN
Das JSR310Module
ist ab Version 2.7 von Jackson veraltet. Stattdessen sollten Sie das Modul registrieren JavaTimeModule
. Es ist immer noch die gleiche Abhängigkeit.
getContext
Methode eine print-Anweisung hinzu . Wenn diese Methode aufgerufen wird, sehe ich keinen Grund dafür, dass dies nicht funktioniert. Wenn es nicht aufgerufen wird, muss es möglicherweise mit der App-Konfiguration behoben werden. Dafür müsste ich mehr sehen, als Sie zur Verfügung gestellt haben. Wie Resteasy-Version, Abhängigkeiten, App-Konfiguration entweder web.xml oder Application-Unterklasse. Grundsätzlich genug, um das Problem zu reproduzierenObjectMapper
swagger" einstellen (in der Frage sehen Sie einen Link). Ich weiß es nicht, da ich nicht viel mit Prahlerei arbeite. Aber ich denke, Prahlerei ist das Hauptproblem, warum der Contextresolver nicht aufgerufen wird.@JsonSerialize und @JsonDeserialize haben bei mir gut funktioniert. Sie machen das zusätzliche jsr310-Modul überflüssig:
Deserializer:
Serializer:
quelle
jackson-datatype-jsr310
. Sie müssen sie nicht manuell in Ihrem Projekt definieren.jackson-datatype-jsr310
.funktioniert gut für mich.
quelle
new com.fasterxml.jackson.datatype.jsr310.JSR310Module()
für Version 2.5.4 von Jackson. Die JavaTimeModule-Klasse ist in dieser Version nicht vorhanden.LocalDateTime
(Jackson 2.9.5). 1 zusätzliche Abhängigkeit erforderlich, so sieht meine build.sbt wie folgt aus:"com.fasterxml.jackson.module" %% "jackson-module-scala" % "2.9.5", "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.9.5"
In Spring Boot Web App, mit Jackson und JSR 310 Version "2.8.5"
Die
@JsonFormat
Arbeiten:quelle
@JsonDeserialize(using= LocalDateDeserializer.class)
@JsonFormat
Nur zum Ändern des Ausgabedatenformats. stackoverflow.com/a/53251526/816759 arbeitet perfekt mit@JsonFormat
,@JsonDeserialize
,@JsonSerialize
spring.jackson.serialization.write-dates-as-timestamps=false
zu Ihremapplication.properties
und es formatiert sie inyyyy-MM-dd
automatisch. Keine Notwendigkeit für@JsonFormat
Die einfachste Lösung (die auch Deserialisierung und Serialisierung unterstützt) ist
Während Sie die folgenden Abhängigkeiten in Ihrem Projekt verwenden.
Maven
Gradle
Es ist keine zusätzliche Implementierung eines ContextResolver, Serializer oder Deserializer erforderlich.
quelle
ObjectMapper
nichtJavaTimeModule
registriert. Wenn Ihre ObjectMapper-Instanz über das spring / MessageConverter-Framework bereitgestellt wird. Sie haben etwas Magie getan, um sie zu verkabeln. In anderen Fällen sollte standardmäßig für alle "LocalDate" in POJOregisterModule
LocalDateDeserializer
Da
LocalDateSerializer
wird es standardmäßig in "[Jahr, Monat, Tag]" (ein JSON-Array) anstatt in "Jahr-Monat-Tag" (ein JSON-String) umgewandelt, und da ich kein speziellesObjectMapper
Setup benötigen möchte (können Sie machenLocalDateSerializer
erzeugen Strings , wenn Sie deaktivieren ,SerializationFeature.WRITE_DATES_AS_TIMESTAMPS
aber das erfordert eine zusätzliche Einrichtung zu IhremObjectMapper
), verwende ich die folgende:Importe:
Code:
Und jetzt kann ich
new ObjectMapper()
meine Objekte einfach ohne spezielle Einstellungen lesen und schreiben.quelle
"2018-12-07"
statt"2018-12-7"
sonst werden Sie eine Fehlermeldung erhalten.yyyy-MM-dd
Format (2-stelliger Monat und Tag), nicht mit dem Formatyyyy-M-d
(1-stelliger Monat oder Tag).Nur ein Update von Christopher Antwort.
Seit der Version 2.6.0
Verwenden Sie das JavaTimeModule anstelle von JSR310Module (veraltet).
Gemäß der Dokumentation verwendet das neue JavaTimeModule standardmäßig dieselben Standardeinstellungen für die Serialisierung, bei der KEINE Zeitzonen-IDs verwendet werden und stattdessen nur ISO-8601-kompatible Zeitzonen-Offsets verwendet werden.
Das Verhalten kann mithilfe von SerializationFeature.WRITE_DATES_WITH_ZONE_ID geändert werden
quelle
MAPPER.registerModule(new JavaTimeModule());
Zeile hinzufügen . Damit kann ich LocalDate-Objekte als "2020-02-20" -Format formatieren. Ich brauchte dieMAPPER.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
Leitung nicht für das, wonach ich suchteDie folgende Anmerkung hat für mich gut funktioniert.
Keine zusätzlichen Abhängigkeiten erforderlich.
quelle
quelle
https://stackoverflow.com/a/53251526/1282532 ist der einfachste Weg, um Eigenschaften zu serialisieren / deserialisieren. Ich habe zwei Bedenken hinsichtlich dieses Ansatzes - bis zu einem gewissen Punkt Verstoß gegen das DRY-Prinzip und hohe Kopplung zwischen Pojo und Mapper.
Wenn Sie POJO mit mehreren LocalDate-Feldern haben, ist es besser, Mapper anstelle von POJO zu konfigurieren. Es kann so einfach sein wie https://stackoverflow.com/a/35062824/1282532, wenn Sie ISO-8601-Werte verwenden ("2019-01-31").
Wenn Sie ein benutzerdefiniertes Format verwenden müssen, sieht der Code folgendermaßen aus:
Die Logik wird nur einmal geschrieben und kann für mehrere POJO wiederverwendet werden
quelle
Bisher einfach und am kürzesten:
Bei Spring boot> = 2.2+ ist keine Abhängigkeit erforderlich
quelle
Ab 2020 und Jackson 2.10.1 ist kein spezieller Code mehr erforderlich. Es geht nur darum, Jackson zu sagen, was Sie wollen:
Dies wurde bereits in dieser Antwort erwähnt . Ich füge einen Komponententest hinzu, der die Funktionalität überprüft:
TestBean verwendet Lombok, um die Boilerplate für die Bohne zu generieren.
quelle
In Konfigurationsklasse definieren LocalDateSerializer und LocalDateDeserializer Klasse und registrieren sie ObjectMapper über JavaTimeModule wie unten:
quelle
Wenn Ihre Anfrage ein Objekt wie das folgende enthält:
Dann können Sie verwenden:
Über dem Feld:
Der Code ist in Kotlin, aber das würde natürlich auch für Java funktionieren.
quelle