2013-05-04 19 views
11

Używam klienta JAX-RS firmy Jersey (wersja 2.0). Wiem, że używa on obiektu Jackson ObjectMapper do generowania i parsowania JSON. Chcę użyć tego samego obiektu do wygenerowania JSON dla niektórych klas java, tak aby można je zapisać w dzienniku.Jak wyodrębnić ObjectMapper z klienta JAX-RS?

Wiem, że mogę utworzyć nową instancję obiektu ObjectMapper, ale wolę poprosić klienta firmy Jersey o podanie odniesienia do tego, którego używa. Jak mogę to zrobić? Jersey 2.0 zna Jacksona, ponieważ zawiera klasę JacksonFeature, która służy przede wszystkim do konfiguracji funkcji Jacksona.

Odpowiedz

18

Rozwiązałem to przez dodanie następujących członków statycznych:

private static JacksonJsonProvider jackson_json_provider = new JacksonJaxbJsonProvider() 
     .configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false) 
     .configure(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS, false); 

private static ObjectMapper object_mapper = jackson_json_provider.locateMapper(
     Object.class, MediaType.APPLICATION_JSON_TYPE); 

private static Client client = ClientBuilder.newClient().register(jackson_json_provider); 

Zauważ, że druga deklaracja nie jest potrzebne jus t skonfigurować FAIL_ON_UNKNOWN_PROPERTIES lub FAIL_ON_EMPTY_BEANS; Używam object_mapper z innych powodów.

+0

Jeśli posiadasz' client', jak wyodrębnić 'objectMapper' z' client'? – DerekY

+0

@DerekY Nie jestem pewien jak to zrobić. – necromancer

17

Jersey tak naprawdę nie konfiguruje jawnie instancji ObjectMapper, zamiast delegować ją do JacksonJsonProvider, która z kolei wykorzystuje domyślną instancję odwzorowującą. Możesz prześledzić, przez the JacksonProviderProxy code, aby zobaczyć, jak to działa. Można tworzyć i dostosowywać do wspólnej mapowania być stosowany w całej aplikacji od zdefiniowania context resolver:

@Provider 
public class ObjectMapperContextResolver implements 
     ContextResolver<ObjectMapper> { 
    private ObjectMapper mapper = null; 

    public ObjectMapperContextResolver() { 
     super(); 

     // Illustrate configuration of the mapper instance 
     mapper = new ObjectMapper().configure(
       SerializationConfig.Feature.WRAP_ROOT_VALUE, true).configure(
       DeserializationConfig.Feature.UNWRAP_ROOT_VALUE, true); 
    } 

    @Override 
    public ObjectMapper getContext(Class<?> type) { 
     return mapper; 
    } 
} 

Dostawca Jackson będzie odzyskać swoje wystąpienie odwzorowujący z tego rezolwerem, i można zrobić to samo w kodzie, a więc :

public class MyResource { 
    @Context 
    private ContextResolver<ObjectMapper> mapperResolver; 

    public void someResourceMethod() { 
     final ObjectMapper mapper = mapperResolver.getContext(Object.class); 
    } 
} 
+0

dziękuję. jak to porównać z moimi 3 wierszami kodu: "private static JacksonJsonProvider ..." (nieczytelne jako komentarz, więc dodałem go jako odpowiedź) – necromancer

+2

również, patrząc na zastrzyki zależne Zastanawiam się, czy twoja metoda działa dla klienta jersey ? lub tylko serwer jersey? – necromancer

+1

@necromancer 'Klient klienta = ClientBuilder.newClient(); client.register (ObjectMapperContextResolver.class); ' – Martin

0

Nie można było dostać się do programu odwzorowującego obiekt bydła, aby go skonfigurować, na podstawie innych rozwiązań tutaj (przy użyciu jackson 2.8.3). (Podejrzewam, że może to być związane z kontenerem osgi, ale mimo to ...) Brutalnym zadaniem jest pobranie obiektu Response od klienta i wywołanie na nim własnej instancji obiektu ObjectMapper. Następnie ta sama instancja może być ponownie użyta z twoją jawną konfiguracją również w innym miejscu.

Client client = ClientBuilder.newClient(); 
ObjectMapper mapper = new ObjectMapper(); 
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 
... 
Response r = client.target(URL).request().get(); 
MyDtoClass dto = mapper.readValue((InputStream)(r.getEntity()), MyDtoClass.class); 
Powiązane problemy