2017-02-26 3 views
4

Ich versuche Antwort auf Marschall so enthält ISO formatierte Datenstand:Registrieren JacksonJsonProvider mit ObjectMapper + JavaTimeModule nach Jersey 2 Kunden

{ 
... 
    "time" : "2014-07-02T04:00:00.000000Z" 
... 
} 

in ZonedDateTime Feld in Objekt meines Domain-Modells. Schließlich funktioniert es, wenn ich Lösung verwende, die in folgendem Schnipsel kommentiert wird. Es gibt viele ähnliche Fragen zu SO, aber ich möchte eine spezifische Antwort bekommen, was ist falsch mit einem anderen Ansatz, der JacksonJsonProvider mit ObjectMapper + JavaTimeModule verwendet?

 ObjectMapper mapper = new ObjectMapper(); 
     mapper.registerModule(new JavaTimeModule()); 
     JacksonJsonProvider provider = new JacksonJsonProvider(mapper); 
     Client client = ClientBuilder.newBuilder() 
//    .register(new ObjectMapperContextResolver(){ 
//     @Override 
//     public ObjectMapper getContext(Class<?> type) { 
//      ObjectMapper mapper = new ObjectMapper(); 
//      mapper.registerModule(new JavaTimeModule()); 
//      return mapper; 
//     } 
//    }) 
       .register(provider) 
       .register(JacksonFeature.class) 
       .build(); 

Fehler erhalte ich:

javax.ws.rs.client.ResponseProcessingException: com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of java.time.ZonedDateTime: no String-argument constructor/factory method to deserialize from String value ('2017-02-24T20:46:05.000000Z') 
at [Source: org.glassfish.jersey.me[email protected]53941c2f 

Projektabhängigkeiten sind:

compile 'com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.8.7' 
compile 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.8.7' 
compile 'com.fasterxml.jackson.core:jackson-core:2.8.7' 
compile 'com.fasterxml.jackson.core:jackson-databind:2.8.7' 
compile 'com.fasterxml.jackson.core:jackson-annotations:2.8.7' 
compile 'org.glassfish.jersey.core:jersey-client:2.25.1' 

bearbeiten

Deserialisierung hier geschieht:

CandlesResponse<BidAskCandle> candlesResponse = webTarget.request() 
       .header(HttpHeaders.AUTHORIZATION,"Bearer "+token) 
       .accept(MediaType.APPLICATION_JSON) 
       .get(new GenericType<CandlesResponse<BidAskCandle>>(){}); 

Antwort

3

Schließlich funktioniert es, wenn ich eine Lösung verwende, die im folgenden Snippet kommentiert wird.

Zunächst fehlt Ihnen eine Abhängigkeit in Ihrer Liste, die Sie auch haben, was das Problem ist.

jersey-media-json-jackson

Dieses Modul ist abhängig von der nativen Jackson Modul, das die JacksonJsonProvider hat. Wenn Sie das JacksonFeature registrieren (das mit jersey-media-json-jackson kommt), registriert es sein eigenes JacksonJaxbJsonProvider, das Vorrang vor allem zu haben scheint, das Sie bereitstellen.

Wenn Sie die ContextResolver verwenden, die JacksonJsonProvider sieht-up eigentlich, dass ContextResolver und verwendet es die ObjectMapper zu lösen. Deshalb funktioniert es. Ob Sie die JacksonFeature verwendet haben oder Ihre eigene JacksonJsonProvider registriert haben (ohne dafür eine ObjectMapper zu konfigurieren), die ContextResovler würde funktionieren.

Eine andere Sache über die jersey-media-json-jackson Modul, es, dass es in Jersey auto-discoverable Mechanismus teilnimmt, der es registriert JacksonFeature ist. Selbst wenn Sie es nicht explizit registriert haben, wird es trotzdem registriert. Die einzigen Möglichkeiten zu vermeiden, eingetragen sind, werden an:

  1. die automatische Erkennung deaktivieren (wie erwähnt in der previous link)
  2. Sie nicht die jersey-media-json-jackson verwenden.Verwenden Sie einfach das native Jackson-Modul jackson-jaxrs-json-provider. Die Sache ist jedoch, dass die jersey-media-json-jackson ein paar Features über das native Modul hinzufügt, also würden Sie diese verlieren.
  3. Nicht getestet, aber es scheint, dass wenn Sie JacksonJaxbJsonProvider anstelle von JacksonJsonProvider verwenden, könnte es funktionieren. Wenn Sie sich die source for the JacksonFeature ansehen, werden Sie sehen, dass es nach einem bereits registrierten JacksonJaxbJsonProvider sucht. Wenn es einen gibt, wird er nicht registriert.

    Die eine Sache, bei der ich mir nicht sicher bin, ist die automatische Erkennung. Die Reihenfolge, in der es registriert wird, wenn es Einfluss darauf hat, ob es Ihre registrierte JacksonJaxbJsonProvider erfasst oder nicht. Etwas, das du ausprobieren kannst. .

+1

Ich wählte Option mit 'JacksonJaxbJsonProvider', wie es einfacher aussieht und keine zusätzlichen Abhängigkeiten beinhaltet. Es funktioniert. –

1

Jackson Konfiguration sieht gut aus, habe ich versucht, die folgenden und war in der Lage, den Wert deserialisieren:

public class Test { 

    public static void main(String[] args) throws Exception { 
     ObjectMapper mapper = new ObjectMapper(); 
     mapper.registerModule(new JavaTimeModule()); 
     Model model = mapper.readValue("{\"time\" : \"2014-07-02T04:00:00.000000Z\"}", Model.class); 
     System.out.println(model.getTime()); 
    } 

} 

class Model{ 
    private ZonedDateTime time; 

    public ZonedDateTime getTime() { 
     return time; 
    } 
    public void setTime(ZonedDateTime time) { 
     this.time = time; 
    } 
} 

Ich kann es reproduzieren, indem mapper.registerModule(new JavaTimeModule()); kommentieren aus. Es sieht also so aus, als ob der Trikot-Client keine benutzerdefinierte mapper-Instanz verwendet. Könnten Sie versuchen, es wie beschrieben here zu konfigurieren.

+0

Versuchte, keine Änderung :( –

+0

@ libnull-dev ich die Antwort aktualisiert haben –

+0

Sie tun dies bedeuten 'ObjectMapper Mapper = new ObjectMapper(); mapper.registerModule (neu JavaTimeModule()); JacksonJsonProvider Anbieter = new JacksonJsonProvider(); provider.setMapper (mapper); ClientConfig config = neuer ClientConfig (provider); Client client = ClientBuilder.newClient (config); 'Allerdings funktioniert das auch nicht. –

Verwandte Themen