3

次のメソッドを持つ JAX-RS WebService があります。

@Path("/myrest")
public class MyRestResource {
...
    @GET
    @Path("/getInteger")
    @Produces(APPLICATION_JSON)
    public Integer getInteger() {
        return 42;
    }

この切り取りを使用してアクセスした場合:

@Test
public void testGetPrimitiveWrapers() throws IOException {
    // this works:
    assertEquals(new Integer(42), new ObjectMapper().readValue("42", Integer.class));
    // that fails:
    assertEquals(new Integer(42), resource().path("/myrest/getInteger").get(Integer.class));
}

次の例外が発生します。

com.sun.jersey.api.client.ClientResponse getEntity
SEVERE: A message body reader for Java class java.lang.Integer, and Java type class java.lang.Integer, and MIME media type application/json was not found
com.sun.jersey.api.client.ClientResponse getEntity
SEVERE: The registered message body readers compatible with the MIME media type are: application/json
...

問題は、単一のプリミティブ値 (int/boolean) またはそれらのラッパー クラスを返すことです。他の POJO クラスを返すことは問題ではないので、JSONConfiguration.FEATURE_POJO_MAPPING および JAXB アノテーションに関するすべての回答はここでは当てはまらないと思います。または、クラス ソースにアクセスできない場合、戻り値の型を記述するためにどの注釈を使用すればよいでしょうか?

ngrep を使用すると、Web サービスから文字列「42」だけが返されることを確認できます。これは有効な JSON「値」ですが、仕様によると有効な JSON「テキスト」ではありません。私の問題はクライアント側にありますか、それともサーバー側にありますか?

http://tugdualgrall.blogspot.de/2011/09/jax-rs-jersey-and-single-element-arrays.htmlに従って JSONConfiguration natural/badgerfish をアクティブ化しようとしましたが、成功しませんでした (ngrep はまだ「42」と表示されます) )。それは正しい道でしょうか?

どんなアイデアでも大歓迎です!

4

1 に答える 1

7

これはJackson で認識されているバグであり、機能として宣伝されています (私の意見では間違っています)。なぜバグだと思うのですか?シリアル化は機能しますが、逆シリアル化は確実に機能しないためです。

いずれにせよ、現在の戻り値の型から有効な JSON を生成することはできないため、ラッパー クラスを作成することをお勧めします。

class Result<T> {
    private T data;

    // constructors, getters, setters
}

@GET
@Path("/getInteger")
@Produces(APPLICATION_JSON)
public Result<Integer> getInteger() {
    return new Result<Integer)(42);
}

またはルート値をラップすることを選択できます。これにより、オブジェクトの単純型名をキーとして、データが最上位の JSON オブジェクトに自動的にカプセル化されます。ただし、このオプションを使用すると、生成されたすべての JSON がラップされることに注意してください (プリミティブ):

final ObjectMapper mapper = new ObjectMapper()
    .configure(SerializationFeature.WRAP_ROOT_VALUE, true)
    .configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);

final String serializedJson = mapper.writeValueAsString(42);
final Integer deserializedVal = mapper.readValue(serializedJson,
        Integer.class);

System.out.println(serializedJson);
System.out.println("Deserialized Value: " + deserializedVal);

出力:

{"Integer":42}逆シリアル化された
値: 42

JAX-RS 環境でインスタンスを取得して構成する方法の詳細については、この回答を参照してください。ObjectMapper

于 2013-05-07T05:29:05.653 に答える