2016-06-28 8 views
1

Ich stehe vor einem sehr bekannten Problem, aber keine Lösung funktioniert für mich. Jede schnelle Hilfe wird dankbar sein.Java 8 LocalDate Konvertierung mit Jackson funktioniert nicht

Von MVC-Controller, rufe ich REST-Service, der mir Modellobjekt mit LocalDate als eines der Felder zurückgibt. JacksonJAXbJSONProvider analysiert das Objekt Localdate nicht. Ich schrieb benutzerdefinierte Mapper wie unten und Abhängigkeit wird in pom.xml hinzugefügt. Weitere erforderliche Abhängigkeiten werden ebenfalls hinzugefügt (jackson databind, Kern, Anmerkung)

<dependency> 
    <groupId>com.fasterxml.jackson.datatype</groupId> 
    <artifactId>jackson-datatype-jsr310</artifactId> 
    <version>2.6.1</version> 
</dependency> 

Individuelle ObjectMapper Klasse:

public class LocalDateObjectMapperContextResolver extends ObjectMapper{ 
    @Provider 
    public LocalDateObjectMapperContextResolver() { 

     registerModule(new JavaTimeModule()); 
     //findAndRegisterModules(); 
     configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); 
    } 

} 

Diese in Java 8 LocalDate Jackson format

Mein spring.xml vorgeschlagen wurde (enthält Konfiguration für MVC Controller etc ...) hat bereits einen Mapper konfiguriert, der die Konvertierung automatisch wie folgt durchführt:

<mvc:annotation-driven> 
    <mvc:message-converters> 
     <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" 
      p:objectMapper-ref="myobjectMapper"/> 
     <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" 
      p:objectMapper-ref="objectMapper"/> 
    </mvc:message-converters> 
</mvc:annotation-driven> 

<bean id="objectMapper" class="org.codehaus.jackson.map.ObjectMapper"/> 
<bean id="myobjectMapper" class="mypackage.LocalDateObjectMapperContextResolver"/> 

Unten ist eine Stubdatei, die eine Verbindung zum REST-Dienst herstellt. Ich habe auch versucht, Anbieter wie unten nach oben nicht funktioniert, aber auch kein Glück hier.

<jaxrs:client id="testclient" 
    serviceClass="package1.RESTService" 
    username="abc" 
    password="abc" 
    address="$serviceURL"> 

    <jaxrs:features> 
     <bean class="org.apache.cxf.transport.common.gzip.GZIPFeature"/> 
     <cxf:logging/> 
    </jaxrs:features> 

    <jaxrs:providers> 
     <bean class="org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider"/> 
     <bean class="mypackage.LocalDateObjectMapperContextResolver"/> 
    </jaxrs:providers> 

</jaxrs:client> 

Jetzt Wie konfiguriere ich meine Context Resolver, die ich gerade geschrieben haben, so dass ich in der Lage sein sollte, LOCALDATE zu konvertieren.

Was mache ich falsch?

Ich erhalte unter Ausnahme

No suitable constructor found for type [simple type, class java.time.LocalDate]: can not instantiate from JSON object (need to add/enable type information?) 
+0

Warum deklarieren Sie botth benutzerdefinierten und ursprünglichen ObjectMapper in Ihrem Spting-Kontext? Ihre Benutzerdefinition erweitert ObjectMapper bereits, sodass Sie nur Ihren benutzerdefinierten Objekt-Mapper deklarieren müssen. Es ist möglich, dass Spring bei der Auswahl eines Nachrichtenkonverters durcheinander gerät und den falschen Objekt-Mapper verwendet. – Matt

+0

Danke für die Antwort Matt, ich stimme Ihrer Argumentation zu.Aber ich habe es aus gutem Grund gemacht, ich arbeite an der Verbesserung der bestehenden Anwendung, wo viele andere MVC-Controller Standard verwenden (von 'Codehaus'), Die, die ich verlängere, ist von 'fasterxml' (die 'LocalDate' unterstützt) und Ich übergebe es an 'MappingJackson2HttpMessageConverter' Lassen Sie mich nur für testingview versuchen, um zu sehen, ob es funktioniert – Surinder

+0

Ok, also Sie verwenden 2 verschiedene Versionen von Jackson zur gleichen Zeit? Es ist generell eine schlechte Übung, obwohl Klassen in verschiedenen Paketen sind. Sie sollten versuchen, die alte Version und den anderen ObjectMapper zu entfernen, nur um dies zu beseitigen. – Matt

Antwort

1

ich es gelöst. Extended ObjectMapper, neues Modul erstellt, Serializer und Deserialzer hinzugefügt und schließlich Modul zu Objectmapper registriert und objectmapper als erstes Argument im JacksonJaxbJsonProvider-Konstruktor übergeben, 2. Argument übergeben ist Standard Annotationen. Unten ist mein Code.

public class MyObjectMapper extends ObjectMapper { 

public MyObjectMapper() { 
    SimpleModule sm = new SimpleModule("SomeName", new Version(1,1,1,"")); 
    sm.addSerializer(LocalDate.class, new JsonSerializer<LocalDate>() { 
     @Override 
     public void serialize(LocalDate value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { 
      ToStringSerializer.instance.serialize(value, jgen, provider); 
     } 
    }); 
    sm.addSerializer(LocalDateTime.class, new JsonSerializer<LocalDateTime>() { 
     @Override 
     public void serialize(LocalDateTime value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { 
      ToStringSerializer.instance.serialize(value, jgen, provider); 
     } 
    }); 
    sm.addDeserializer(LocalDate.class, new JsonDeserializer<LocalDate>() { 
     @Override 
     public LocalDate deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { 
      return LocalDate.parse(jp.getText()); 
     } 
    }); 
    sm.addDeserializer(LocalDateTime.class, new JsonDeserializer<LocalDateTime>() { 
     @Override 
     public LocalDateTime deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { 
      return LocalDateTime.parse(jp.getText()); 
     } 
    }); 
    registerModule(sm); 
} 

Server Side-Konfiguration:

<bean id="mapper" class="mymapperpkg.MyObjectMapper"/> 

<jaxrs:server> 
...... 
..... 
<jaxrs:serviceBeans>....</jaxrs:serviceBeans> 
...... 
...... 

<bean class="org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider"> 
       <constructor-arg index="0" ref="mapper"/> 
       <constructor-arg index="1"> 
        <util:constant static-field="org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider.DEFAULT_ANNOTATIONS"/> 
       </constructor-arg> 
      </bean> --> 

</jaxrs:server> 

Client-Seite configarion

<bean id="mapper" class="mymapperpkg.MyObjectMapper"/> 

<jaxrs:client id="deliveryItemClient" 
       serviceClass="servicepkg.YourRESTServiceClass" 
       username="adadsad" 
       password="asdasdasd" 
       address="adresss to deployed service"> 


     <jaxrs:providers> 
      <bean class="org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider"> 
       <constructor-arg index="0" ref="mapper"/> 
       <constructor-arg index="1"> 
        <util:constant static-field="org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider.DEFAULT_ANNOTATIONS"/> 
       </constructor-arg> 
      </bean> 
     </jaxrs:providers> 

    </jaxrs:client> 

Dies ist, wenn REST Anwendung LOCALDATE erzeugt.

Wenn REST Anwendung LOCALDATE verbraucht, können Sie schreiben ParamHanlder wie unten und registrieren diese unter Anbieter in jaxrs JSON-String zurück zu LOCALDATE zu analysieren: Server

MyCustomParamHandler implements Paramhandler<Localdate>{ 

LocalDate fromString(String jsonString){ 
      return LocalDate.parse(jsonString); 
    } 
} 

Prost!