web-dev-qa-db-ja.com

Jersey:StringからArrayListのインスタンスを逆シリアル化できません

私はjsonベースのREST Webサービスを使用して実装しています:Jetty、Jersey、Jersey-JSONをJacksonを使用して実装しています。

私のメソッドの1つは、List <String>型のフィールドを持つPersonインスタンスを受け取ります。例:

Public class Person {
    List<String> names;
}

名前の配列で呼び出すと、すべて正常に機能します。例えば。:

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

しかし、その人の名前が1つしかない場合、クライアントは次のように単一の値要素を作成します。

{ "names" : "Jhon" } 

単一の値でサービスを呼び出そうとすると、例外が発生します。

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

質問:

配列フィールドが単一の要素として送信されたときに配列フィールドを非直列化できるようにするには、Webサービスをどのように作成/構成する必要がありますか?.

-

私はすでに読んだ:

Jackson逆シリアル化-含まれているArrayList <T>を使用

そして

JAXBオブジェクトのリストのシリアル化をJSONにカスタマイズするにはどうすればよいですか?

そしてこれは最後の答えを参照します:

ジャージークライアントは、jsonサービスをデシリアライズできません-例外(インスタンスをデシリアライズできません)

Jaxb jsonに1つの要素配列の括弧がありません

しかし、それらのどれも問題を解決しません。

前もって感謝します!

13
lpinto.eu

長い一日のあと、また...たくさんのウィキやFAQを読んだ後、ようやく動きました。

私がしたこと:

  1. ジャクソンを使う
  2. ジャクソンプロバイダーの使用を強制する
  3. カスタムデシリアライザを定義する
  4. aCCEPT_SINGLE_VALUE_AS_ARRAYフラグをアクティブにする
  5. 依存関係を修正する

物語:

デフォルトでjaxb(I belive)を使用するJersey 1.13を使用していました。

私はそれをジャクソンを使うように変更しました

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

で説明されているように:

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

これにより、私のジャージはジャクソンを使用しましたが、問題は残っています。ジャクソンはまだ配列をデシリアライザできません。

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/66099

必要なステップでしたが、十分ではありませんでした。 ACCEPT_SINGLE_VALUE_AS_ARRAYフラグを有効にする必要があります。

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

カスタムデシリアライザを定義する必要がありました

public class MyResolver implements ContextResolver<ObjectMapper> {

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

それを行うには:

Customizing-ObjectMapper

これをすべて行った後も、それはうまくいきませんでした...

さらに検索を行ったところ、次のことがわかりました。

Jackson 2.0とJersey 1.12

依存関係の問題について議論しています。

これは私の問題を明らかにしました、Jersey v1.13Jackson v1.9.2と共に出荷されますJackson v2.0が必要です

ジャクソン1.9.2が含まれていたため、jersey-jsonの依存関係を削除しました。

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

そして直接依存関係を宣言します:

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

参照:

jackson-jaxrs-json-provider

注:この変更により、Jaxbまたはjettisonを使用するJersey機​​能が削除されます。

オフトピック、誰かにとって興味深いかもしれません:

JSONフィールドの命名に@XmlElementフィールドアノテーションを使用しないようにJersey/Jacksonを設定

12
lpinto.eu

JsonFormat アノテーションを使用して、クラス、フィールド、またはメソッドレベルのアノテーションでこれを行うことができます

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

このページ の例5.10および5.11は、正確な問題を説明しています。次のように、JSONビルダーを構成して単一アイテムリストの配列を強制できます:JSONConfiguration.mapped().arrays("names").build()

1
rmhartog

クラスに@JsonSerializeを追加することでうまくいきました

@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"}]}}

このタイプの方法... yahoo place apiを使用する場合

1
Zaric