2013-01-14 10 views
10

Mam usługę WWW REST opartą na json zaimplementowaną za pomocą: Jetty, Jersey, Jersey-JSON z wykorzystaniem Jackson.Jersey: Nie można deserializować instancji ArrayList z ciągu

Jedna z moich metod otrzymuje instancję Osoba, która ma pole typu Lista < Ciąg >. tj .:

Public class Person { 
    List<String> names; 
} 

Jeśli ja to nazywam z tablicą nazw, wszystko działa ok! np:

{ "names" : [ "Jhon", "Doe" ] } 

Ale jeśli człowiek ma tylko jedno imię, mój klient tworzy element wartość pojedynczej, np

{ "names" : "Jhon" } 

Kiedy próbuję wywołać usługę z pojedynczej wartości, otrzymuję wyjątek:

Can not deserialize instance of java.util.ArrayList out of VALUE_STRING token 

Pytanie:

W jaki sposób powinienem utworzyć/skonfigurować moją usługę sieciową, aby móc deserializować pole tablicy, kiedy są one wysyłane do mnie jako pojedynczy element.

-

ja już przeczytać:

Jackson deserialization - with contained ArrayList<T>

i

How can I customize serialization of a list of JAXB objects to JSON?

i to, że odnoszą się ostatnią odpowiedź:

Jersey client can not deserializable json services - exception(can not deserialize instance)

Jaxb json missing brackets for one element array

Ale żaden z tych rozwiązać problem.

Z góry dziękuję!

Odpowiedz

11

Po długim dniu i kolejnym ... po przeczytaniu wielu wiki i faqs, w końcu działa.

Co zrobiłem:

  1. Zastosowanie Jackson
  2. Siła Jackson dostawcy Wykorzystanie
  3. zdefiniować swoje własne Deserializator
  4. aktywować flagę ACCEPT_SINGLE_VALUE_AS_ARRAY
  5. Fix zależności

Fabuła:

Używałem systemu Jersey 1.13, który domyślnie używa (ja wierzę) jaxb.

Zmieniłem go użytku Jackson

<init-param> 
    <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name> 
    <param-value>true</param-value> 
</init-param> 

jak opisano w:

https://stackoverflow.com/a/13895768/660990

To sprawiło mój Koszulka używać Jacksona, ale problem pozostaje; jackson nie może jeszcze deserializować tablicy.

Zmusiłem wykorzystanie dostawców Jackson:

<init-param> 
    <param-name>com.sun.jersey.config.property.packages</param-name> 
    <param-value> 
     your.project.packages; 
     org.codehaus.jackson.jaxrs</param-value> 
</init-param> 

https://stackoverflow.com/a/3143214/660990

Był potrzebny krok, ale nie wystarczająco. Konieczne jest aktywowanie flagi ACCEPT_SINGLE_VALUE_AS_ARRAY.

ObjectMapper objectMapper; 
objectMapper = new ObjectMapper().configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); 

Potrzebowałem określić zwyczaj Deserializator

public class MyResolver implements ContextResolver<ObjectMapper> { 

@Override 
    public ObjectMapper getContext(final Class<?> objectType) { 
     ...    
     return objectMapper; 
    } 
} 

w tym celu:

Customizing-ObjectMapper

Po zrobieniu tego wszystkiego nadal nie działa ...

Po trochę więcej czasu wyszukiwania, znalazłem:

Jackson 2.0 with Jersey 1.12

który omawia Zależności problemy ..

Ten rozkoszował mój problem, Jersey v1.13 statki z Jackson v1.9.2 muszę Jackson v2.0

Usunąłem zależność dla jersey-json, ponieważ zawierało jackson 1.9.2:

<dependency> 
    <groupId>com.sun.jersey</groupId> 
    <artifactId>jersey-json</artifactId> 
</dependency> 

i jest bezpośrednio uznany za zależność:

<dependency> 
    <groupId>com.fasterxml.jackson.jaxrs</groupId> 
    <artifactId>jackson-jaxrs-json-provider</artifactId> 
</dependency> 

referencyjny:

jackson-jaxrs-json-provider

Uwaga: zmiana ta usuwa zdolność do korzystania z Jersey JAXB lub odrzucić.

Off temacie, mogą być interesujące dla kogoś:

Configure Jersey/Jackson to NOT use @XmlElement field annotation for JSON field naming

+0

Dzięki mate, następująca linia rozwiązała mój problem: objectMapper = new ObjectMapper(). Configure (DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); – mojsilo

+0

@mojsilo gdzie wstawiasz ** objectMapper = new ObjectMapper(). Configure (DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); ** ? – Luke

+0

Umieściłem go w konstruktorze usługi mapper.configure (\t \t org.codehaus.jackson.map.DeserializationConfig.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); – mojsilo

1

Przykład 5.10 i 5.11 z this page wyjaśnić dokładny problem. Możesz skonfigurować program budujący JSON, aby wymusić tablice dla list pojedynczych elementów, na przykład: JSONConfiguration.mapped().arrays("names").build().

+1

dziękuję! Ale chcę to naprawić po stronie serwera. Zaktualizowano moje pytanie, aby było wyraźne. –

+0

Gdzie można dodać ** JSONConfiguration.mapped(). Tablice ("nazwy"). Build() ** w kliencie? Po skonstruowaniu żądania, ale przed wysłaniem? – Luke

1

on pracował dla mnie przez dodanie @JsonSerialize do klasy

@JsonSerialize 
Public class Person { 
    List<String> names; 
} 
0
{"results": {"place": {"lang": "en-US","woeid": "2168606"}}} 

&

{"results": {"place": [{"lang": "en-US","woeid": "2168606"}, {"lang": "en-US","woeid": "2168606"}]}} 

tego typu, jak to zrobić ... miejsce podczas korzystania yahoo api

1

Można to zrobić z adnotacji na poziomie metody klasy, pola lub używając JsonFormat adnotacji

@JsonFormat(with = Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) 
protected List<String> list; 

public List<String> getList() { 
    return list; 
} 

public void setList(List<String> list) { 
    this.list = list; 
} 
Powiązane problemy