Comment désérialiser Joda DateTime à l'aide de Jackson avec Jersey 2 Client dans Spring MVC?
J'ai été le dénigrement de ma tête avec cette preuve de concept pendant un certain temps. Je veux consommer un point de terminaison REST que revient la charge utile JSON avec un ISO8601 UTC timestamp:
{ ...
"timestamp" : "2014-08-20T11:51:31.233Z"
}
et je veux l'exploiter à l'aide d'une ligne de commande client Java écrit un Maillot 2 client avec Jackson/le Printemps de Démarrage. La gare de POJO est définie comme suit:
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(Include.NON_NULL)
public class GreetingResource
{
@JsonProperty("timestamp")
private DateTime date;
...
}
Après les recommandations suivantes montré dans:
https://jersey.java.net/documentation/latest/user-guide.html#json.jackson
et à l'aide de la suite de Gradle dépendances:
dependencies {
compile("org.springframework.boot:spring-boot-starter")
compile("org.springframework.boot:spring-boot-starter-logging")
compile("joda-time:joda-time")
compile("com.fasterxml.jackson.core:jackson-core")
compile("com.fasterxml.jackson.core:jackson-annotations")
compile("com.fasterxml.jackson.core:jackson-databind")
compile("com.fasterxml.jackson.datatype:jackson-datatype-joda")
compile("com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:2.3.3")
compile("org.apache.commons:commons-lang3:3.3.2")
compile("org.glassfish.jersey.core:jersey-client:2.2")
compile("org.glassfish.jersey.media:jersey-media-json-jackson:2.2")
testCompile("org.springframework.boot:spring-boot-starter-test")
}
J'ai toujours cette erreur:
Exception in thread "main" javax.ws.rs.ProcessingException: Error reading entity from input stream.
at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:849)
at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:768)
at org.glassfish.jersey.client.InboundJaxrsResponse.readEntity(InboundJaxrsResponse.java:96)
at org.glassfish.jersey.client.ScopedJaxrsResponse.access$001(ScopedJaxrsResponse.java:56)
at org.glassfish.jersey.client.ScopedJaxrsResponse$1.call(ScopedJaxrsResponse.java:77)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
at org.glassfish.jersey.internal.Errors.process(Errors.java:228)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:397)
at org.glassfish.jersey.client.ScopedJaxrsResponse.readEntity(ScopedJaxrsResponse.java:74)
at client.GreetingClient.processResponse(GreetingClient.java:62)
at client.GreetingClient.performGet(GreetingClient.java:53)
at client.GreetingService.internalLoadGreeting(GreetingService.java:44)
at client.GreetingService.LoadGreeting(GreetingService.java:27)
at client.Application.main(Application.java:25)
Caused by: com.fasterxml.jackson.databind.JsonMappingException: Can not instantiate value of type [simple type, class org.joda.time.DateTime] from String value ('2014-08-20T12:19:36.358Z'); no single-String constructor/factory method (through reference chain: client.GreetingResource["timestamp"])
at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator._createFromStringFallbacks(StdValueInstantiator.java:428)
at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.createFromString(StdValueInstantiator.java:299)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromString(BeanDeserializerBase.java:1150)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:139)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:126)
at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:525)
at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:99)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:242)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:118)
at com.fasterxml.jackson.databind.ObjectReader._bind(ObjectReader.java:1233)
at com.fasterxml.jackson.databind.ObjectReader.readValue(ObjectReader.java:677)
at com.fasterxml.jackson.jaxrs.base.ProviderBase.readFrom(ProviderBase.java:777)
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.aroundReadFrom(ReaderInterceptorExecutor.java:188)
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:134)
J'ai abandonné. Ce que je fais mal?
Le client est configuré comme suit:
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Invocation.Builder;
import javax.ws.rs.client.WebTarget;
import org.glassfish.jersey.client.ClientConfig;
...
@Component
public class GreetingClient
{
private final WebTarget serviceWebTarget;
{
ClientConfig config = new ClientConfig();
config.register(MyObjectMapperProvider.class);
config.register(JacksonFeatures.class);
Client client = ClientBuilder.newClient(config);
this.serviceWebTarget = client.target("http://myserver:8080");
}
...
}
Le fournisseur enregistré est définie comme (dans le même package que le client):
@Provider
public class MyObjectMapperProvider implements ContextResolver<ObjectMapper>
{
private final static DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
@Override
public ObjectMapper getContext(Class<?> type)
{
final ObjectMapper result = new JodaMapper();
result.setDateFormat(dateFormat);
return result;
}
}
J'ai essayé avec/sans enregistrer le fournisseur et aussi en annotant le champ à utiliser DateTimeDeserializer (via @JsonDeserialize) - seulement pour obtenir une erreur, car "il n'y a pas de valeur par défaut pas de-arg constructeur disponibles".
Si j'utilise java standard.util.Date de la place avec
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
il fonctionne comme un jeu d'enfant.
Des indices? Merci pour votre aide.
- Avez-vous essayé d'utiliser la Joda Jackson module? github.com/FasterXML/jackson-datatype-joda
- oui, à partir de mon code je suis un lien vers com.fasterxml.jackson.type de données:jackson-type de données-joda
Vous devez vous connecter pour publier un commentaire.
Ci-dessous test OK:
Maven configuration:
@JsonProperty("timestamp")
a été source de confusion. Je pensais que c'était quelque chose qui était nécessaire pour que le JodaModule pour gérer la conversion correctement, mais il change juste la résultante désérialisé json nom de la propriété à partir de la "date" (nom de la classe de terrain) afin de "timestamp".Pour quelqu'un d'autre d'avoir des problèmes, aucune des autres réponses étaient vraiment bien se complète donc sa ce
J'ai rencontré le même problème. Ce que vous avez à faire est de s'inscrire personnalisé ObjectMapper en Jersey:
Piotor Glazar œuvres de l'un mais pas l'autre. (Il va écrire la date sous la forme d'un timestamp, plutôt que de ISO8601 UTC.)
Un changement de sa solution est de désactiver SerializationFeature.WRITE_DATES_AS_TIMESTAMPS.
Voici la solution qui a fonctionné pour moi.
Si vous souhaitez obtenir les mêmes dans le projet J2EE pour Jersy client, veuillez consulter le code ci-dessous.
Et la Date DeSerialiser est ci-dessous,
Espère que cela va vous aider.