web-dev-qa-db-ger.com

Jersey: Instanz von ArrayList kann nicht aus String deserialisiert werden

Ich habe einen json-basierten REST Web-Service, der mithilfe von: Jetty, Jersey, Jersey-JSON mit Jackson implementiert wurde.

Eine meiner Methoden empfängt eine Personeninstanz, die ein Feld vom Typ List <String>. D. H.

Public class Person {
    List<String> names;
}

Wenn ich es mit einem Array von Namen benenne, funktioniert alles in Ordnung! z.B.:

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

Wenn die Person nur einen Namen hat, erstellt mein Kunde ein einzelnes Wertelement, z. B .:

{ "names" : "Jhon" } 

Wenn ich versuche, den Dienst mit einem einzigen Wert aufzurufen, erhalte ich eine Ausnahme:

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

Frage:

Wie soll ich meinen Web-Service erstellen/konfigurieren, um das Array-Feld deserialisieren zu können, wenn es als einzelnes Element an mich gesendet wird.

-

Ich habe schon gelesen:

Jackson Deserialisierung - mit enthaltener ArrayList <T>

und

Wie kann ich die Serialisierung einer Liste von JAXB-Objekten an JSON anpassen?

und das bezieht sich auf die letzte Antwort:

Jersey-Client kann keine deserialisierbaren Json-Services - Ausnahme (Instanz kann nicht deserialisiert werden)

Jaxb Json fehlende Klammern für ein Element-Array

Aber nichts davon löst das Problem.

Danke im Voraus!

11
lpinto.eu

Nach einem langen Tag und einem weiteren ... nachdem er viele Wikis und FAQs gelesen hatte, klappt es endlich.

Was ich getan habe:

  1. Verwenden Sie Jackson
  2. Erzwingen Sie die Verwendung von Jackson-Anbietern
  3. Definieren Sie einen benutzerdefinierten Deserializer
  4. aktivieren Sie das Flag ACCEPT_SINGLE_VALUE_AS_ARRAY
  5. Abhängigkeiten beheben

Die Geschichte:

Ich habe Jersey 1.13 verwendet, das standardmäßig Jaxb verwendet (ich glaube daran).

Ich änderte es in verwende Jackson  

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

wie beschrieben bei:

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

Dies veranlasste mein Trikot, Jackson zu benutzen, aber das Problem bleibt bestehen; jackson kann das Array noch nicht deserialisieren.

Ich habe die Verwendung von Jackson Anbietern erzwungen.

<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

War ein notwendiger Schritt, aber nicht genug. Das Flag ACCEPT_SINGLE_VALUE_AS_ARRAY muss aktiviert werden.

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

Ich brauchte definierte benutzerdefinierte Deserializer

public class MyResolver implements ContextResolver<ObjectMapper> {

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

um das zu tun:

Customizing-ObjectMapper

Nach all dem funktionierte es immer noch nicht ...

Nach längerer Suche fand ich:

Jackson 2.0 mit Jersey 1.12

Das bespricht Abhängigkeiten Probleme ..

Das hat mir das Problem gezeigt. Jersey v1.13 wird mit Jackson v1.9.2 geliefert. Ich brauche Jackson v2.0

Ich habe die Abhängigkeit für Jersey-Json aufgehoben, weil es Jackson 1.9.2 enthielt:

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

Und direkt deklarierte Abhängigkeit für:

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

Referenz:

jackson-jaxrs-json-provider

Hinweis: Durch diese Änderung wird die Jersey-Fähigkeit zur Verwendung von Jaxb oder Abwurf entfernt.

Off topic , kann für jemanden interessant sein:

Konfigurieren Sie Jersey/Jackson so, dass keine @XmlElement-Feldanmerkung für die Benennung von JSON-Feldern verwendet wird

11
lpinto.eu

Sie können dies mit Annotationen auf Klassen-, Feld- oder Methodenebene mit der Annotation JsonFormat tun

@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;
}
2
steven35

Die Beispiele 5.10 und 5.11 auf dieser Seite erklären genau Ihr Problem. Sie können den JSON-Builder so konfigurieren, dass Arrays für Listen mit einzelnen Elementen erzwungen werden. JSONConfiguration.mapped().arrays("names").build().

1
rmhartog

Es hat für mich funktioniert, indem @JsonSerialize zur Klasse hinzugefügt wurde

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

&

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

diese Art, wie zu tun ... bei der Verwendung von Yahoo Place API

1
Zaric