13

Jetty、Jersey、Jersey-Jacksonを使用したJSONを使用して実装されたjsonベースのRESTWebサービスがあります。

私のメソッドの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サービスをどのように作成/構成する必要がありますか。

-

私はすでに読んだ:

ジャクソンの逆シリアル化-含まれているArrayList<T>

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

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

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

Jaxbjsonに1つの要素配列の角かっこがありません

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

前もって感謝します!

4

5 に答える 5

14

長い一日の後、そして別の...多くのウィキやよくある質問を読んだ後、それはついに機能します。

私がしたこと:

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

物語:

私はデフォルトで(私は信じている)jaxbを使用するJersey1.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/660990

これにより、私のジャージはジャクソンを使用するようになりましたが、問題は残っています。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

必要なステップでしたが、十分ではありませんでした。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;
    }
}

それを行うために:

カスタマイズ-ObjectMapper

これをすべて行った後でも、それは機能しませんでした...

もう少し検索した後、私は見つけました:

ジャクソン2.0とジャージー1.12

依存関係の問題について説明します。

これは私の問題を明らかにしました、ジャージーv1.13はジャクソンv1.9.2と一緒に出荷されます私はジャクソンv2.0が必要です

jackson 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を構成します

于 2013-01-18T16:07:11.253 に答える
5

これは、 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;
}
于 2016-11-16T12:26:33.800 に答える
1

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

于 2013-01-14T13:51:13.693 に答える
1

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

@JsonSerialize
Public class Person {
    List<String> names;
}
于 2014-09-30T22:14:32.497 に答える
1
{"results": {"place": {"lang": "en-US","woeid": "2168606"}}}

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

このタイプの方法...yahooplaceapiを使用する場合

于 2015-08-13T13:27:05.707 に答える