Je n'ai jamais pu faire fonctionner cela simplement en utilisant des annotations. Pour le faire fonctionner, j'ai créé un ContextResolver
for ObjectMapper
, puis j'ai ajouté le JSR310Module
( update: now it is JavaTimeModule
instead ), avec une autre mise en garde, qui était la nécessité de définir write-date-as-timestamp sur false. Pour en savoir plus, consultez la documentation du module JSR310 . Voici un exemple de ce que j'ai utilisé.
Dépendance
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.4.0</version>
</dependency>
Remarque: un problème auquel j'ai été confronté est que la jackson-annotation
version extraite par une autre dépendance, utilisait la version 2.3.2, qui annulait la version 2.4 requise par le jsr310
. Ce qui s'est passé, c'est que j'ai obtenu un NoClassDefFound pour ObjectIdResolver
, qui est une classe 2.4. J'avais donc juste besoin d'aligner les versions de dépendances incluses
ContexteResolver
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;
}
}
Classe de ressources
@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;
}
}
Tester
curl -v http://localhost:8080/api/person
Résultat: {"birthDate":"2015-03-01"}
curl -v -POST -H "Content-Type:application/json" -d "{\"birthDate\":\"2015-03-01\"}" http://localhost:8080/api/person
Résultat: 2015-03-01
Voir aussi ici pour la solution JAXB.
METTRE À JOUR
Le JSR310Module
est obsolète à partir de la version 2.7 de Jackson. Au lieu de cela, vous devez enregistrer le module JavaTimeModule
. C'est toujours la même dépendance.
getContext
méthode. Si cette méthode est appelée, je ne vois pas de raison pour que cela ne fonctionne pas. S'il n'est pas appelé, il se peut que ce soit quelque chose qui doit être corrigé avec la configuration de l'application. Pour cela, j'aurais besoin de voir plus que ce que vous avez fourni. Comme la version Resteasy, les dépendances, la configuration de l'application web.xml ou la sous-classe Application. En gros, assez pour reproduire le problèmeObjectMapper
comme le fait swagger (vous pouvez voir un lien dans la question). Je ne sais pas car je ne travaille pas beaucoup avec swagger. Mais je pense que le swagger est le principal problème, pourquoi le résolveur de contexte n'est pas appelé.@JsonSerialize et @JsonDeserialize ont bien fonctionné pour moi. Ils éliminent le besoin d'importer le module jsr310 supplémentaire:
Désérialiseur:
Sérialiseur:
la source
jackson-datatype-jsr310
. Pas besoin de les définir manuellement dans votre projet.jackson-datatype-jsr310
.fonctionne bien pour moi.
la source
new com.fasterxml.jackson.datatype.jsr310.JSR310Module()
pour la version 2.5.4 de Jackson. La classe JavaTimeModule n'existe pas dans cette version.LocalDateTime
(jackson 2.9.5). 1 dépendance supplémentaire requise, donc mon build.sbt ressemble à:"com.fasterxml.jackson.module" %% "jackson-module-scala" % "2.9.5", "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.9.5"
Dans l'application Web Spring Boot, avec Jackson et JSR 310 version "2.8.5"
Les
@JsonFormat
oeuvres:la source
@JsonDeserialize(using= LocalDateDeserializer.class)
@JsonFormat
juste pour changer le format des données de sortie. stackoverflow.com/a/53251526/816759 fonctionne parfaitement avec@JsonFormat
,@JsonDeserialize
,@JsonSerialize
spring.jackson.serialization.write-dates-as-timestamps=false
à votreapplication.properties
, et il le formateyyyy-MM-dd
automatiquement. Pas besoin de@JsonFormat
La solution la plus simple (qui prend également en charge la désérialisation et la sérialisation) est
Lors de l'utilisation des dépendances suivantes dans votre projet.
Maven
Gradle
Aucune implémentation supplémentaire d'un ContextResolver, Serializer ou Deserializer n'est requise.
la source
ObjectMapper
ne vous soyez pasJavaTimeModule
inscrit. Si votre instance ObjectMapper est fournie à partir du framework spring / MessageConverter. Ils ont fait de la magie pour les relier. Dans les autres cas, devraitregisterModule
activerLocalDateDeserializer
par défaut pour tous les "LocalDate" dans POJODepuis le
LocalDateSerializer
transforme en "[année, mois, jour]" (un tableau json) plutôt qu'en "année-mois-jour" (une chaîne json) par défaut, et puisque je ne veux pas avoir besoin deObjectMapper
configuration spéciale (vous pouvez faitesLocalDateSerializer
générer des chaînes si vous désactivezSerializationFeature.WRITE_DATES_AS_TIMESTAMPS
mais cela nécessite une configuration supplémentaire à votreObjectMapper
), j'utilise ce qui suit:importations:
code:
Et maintenant, je peux simplement utiliser
new ObjectMapper()
pour lire et écrire mes objets sans aucune configuration particulière.la source
"2018-12-07"
au lieu de"2018-12-7"
cela, vous obtiendrez une erreur.yyyy-MM-dd
format (mois et jour à 2 chiffres) et non avec le formatyyyy-M-d
(mois ou jour à 1 chiffre).Juste une mise à jour de la réponse de Christopher.
Depuis la version 2.6.0
Utilisez JavaTimeModule au lieu de JSR310Module (obsolète).
Selon la documentation , le nouveau JavaTimeModule utilise les mêmes paramètres standard pour la sérialisation par défaut qui n'utilise PAS les ID de fuseau horaire, et utilise à la place uniquement les décalages de fuseau horaire conformes à ISO-8601.
Le comportement peut être modifié à l'aide de SerializationFeature.WRITE_DATES_WITH_ZONE_ID
la source
MAPPER.registerModule(new JavaTimeModule());
ligne. Cela m'a permis de formater les objets LocalDate au format "2020-02-20". Je n'avais pas besoin de laMAPPER.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
ligne, pour ce que je cherchaisL'annotation suivante a bien fonctionné pour moi.
Aucune dépendance supplémentaire nécessaire.
la source
la source
https://stackoverflow.com/a/53251526/1282532 est le moyen le plus simple de sérialiser / désérialiser la propriété. J'ai deux préoccupations concernant cette approche - jusqu'à un certain point la violation du principe DRY et un couplage élevé entre pojo et mapper.
Dans le cas où vous avez POJO avec plusieurs champs LocalDate, il est préférable de configurer mapper au lieu de POJO. Cela peut être aussi simple que https://stackoverflow.com/a/35062824/1282532 si vous utilisez des valeurs ISO-8601 ("2019-01-31")
Au cas où vous auriez besoin de gérer un format personnalisé, le code ressemblera à ceci:
La logique est écrite une seule fois, elle peut être réutilisée pour plusieurs POJO
la source
Le plus simple et le plus court à ce jour:
aucune dépendance requise avec Spring boot> = 2.2+
la source
À partir de 2020 et Jackson 2.10.1, aucun code spécial n'est nécessaire, il suffit de dire à Jackson ce que vous voulez:
Cela a déjà été mentionné dans cette réponse , j'ajoute un test unitaire vérifiant la fonctionnalité:
TestBean utilise Lombok pour générer le passe-partout pour le bean.
la source
Dans la classe de configuration, définissez la classe LocalDateSerializer et LocalDateDeserializer et enregistrez-les dans ObjectMapper via JavaTimeModule comme ci-dessous:
la source
Si votre demande contient un objet comme celui-ci:
Ensuite, vous pouvez utiliser:
Au-dessus du terrain:
Le code est en Kotlin mais cela fonctionnerait aussi bien sûr pour Java.
la source