私はこれを行う方法を見つけようとしてお尻をグーグルで探しています:私はジャージーRESTサービスを持っています。RESTサービスを呼び出すリクエストJSONオブジェクト。私の質問は、Jersey POSTメソッド実装から、HTTPリクエストの本文にあるJSONにアクセスするにはどうすればよいですか?
サンプルコードへのヒント、トリック、ポインターは大歓迎です。
ありがとう...
-スティーブ
JSON文字列自体を取得する方法がわかりませんが、次のように含まれているデータを取得できます。
リクエストで渡されるJSONオブジェクトと同じ構造を持つJAXBアノテーション付きJavaクラス(C)を定義します。
例えばJSONメッセージの場合:
{
"A": "a value",
"B": "another value"
}
次のようなものを使用します。
@XmlAccessorType(XmlAccessType.FIELD)
public class C
{
public String A;
public String B;
}
次に、タイプCのパラメーターを使用してリソースクラスでメソッドを定義できます。Jerseyがメソッドを呼び出すと、POSTされたJSONオブジェクトに基づいてJAXBオブジェクトが作成されます。
@Path("/resource")
public class MyResource
{
@POST
public put(C c)
{
doSomething(c.A);
doSomethingElse(c.B);
}
}
既に提案したように、_@Consumes
_ Content-Typeを_text/plain
_に変更しても機能しますが、REST APIの観点からは正しくないようです。
顧客がAPIに対してPOST JSONを使用する必要があるが、Content-Typeヘッダーを_text/plain
_として指定する必要があることを想像してください。私の意見では、きれいではありません。 JSONの場合、リクエストヘッダーは_Content-Type: application/json
_を指定する必要があります。
JSONを受け入れるが、POJOではなくString
オブジェクトにシリアル化するために、カスタム MessageBodyReader を実装できます。この方法で行うのも同じくらい簡単で、APIの仕様を妥協する必要はありません。
MessageBodyReader のドキュメントを読む価値があるので、どのように機能するかを正確に知っています。これは私がやった方法です:
ステップ1.カスタムの実装 MessageBodyReader (
_@Provider
@Consumes("application/json")
public class CustomJsonReader<T> implements MessageBodyReader<T> {
@Override
public boolean isReadable(Class<?> type, Type genericType,
Annotation[] annotations,MediaType mediaType) {
return true;
}
@Override
public T readFrom(Class<T> type, Type genericType, Annotation[] annotations,
MediaType mediaType, MultivaluedMap<String, String> httpHeaders,
InputStream entityStream) throws IOException, WebApplicationException {
/* Copy the input stream to String. Do this however you like.
* Here I use Commons IOUtils.
*/
StringWriter writer = new StringWriter();
IOUtils.copy(entityStream, writer, "UTF-8");
String json = writer.toString();
/* if the input stream is expected to be deserialized into a String,
* then just cast it
*/
if (String.class == genericType)
return type.cast(json);
/* Otherwise, deserialize the JSON into a POJO type.
* You can use whatever JSON library you want, here's
* a simply example using GSON.
*/
return new Gson().fromJson(json, genericType);
}
}
_
上記の基本的な概念は、入力ストリームがString
(_Type genericType
_で指定される)に変換されると予想されるかどうかをチェックすることです。その場合、指定されたtype
(これはString
になります)にJSONをキャストするだけです。予想されるタイプが何らかのPOJOである場合、JSONライブラリ(例:JacksonまたはGSON)を使用して、それをPOJOにデシリアライズします。
ステップ2. MessageBodyReaderをバインドします
これは、使用しているフレームワークによって異なります。 GuiceとJerseyがうまく機能していることがわかります。 Guiceで MessageBodyReader をバインドする方法は次のとおりです。
私の JerseyServletModule のようにリーダーをバインドします-
bind(CustomJsonReader.class).in(Scopes.SINGLETON);
上記のCustomJsonReader
は、JSONペイロードをPOJOにデシリアライズします。また、単に生のJSONが必要な場合は、String
オブジェクトです。
この方法で行う利点は、_Content-Type: application/json
_を受け入れることです。つまり、リクエストハンドラーはJSONを消費するように設定できますが、これは適切だと思われます。
_@POST
@Path("/stuff")
@Consumes("application/json")
public void doStuff(String json) {
/* do stuff with the json string */
return;
}
_
Jerseyは、JettisonタイプのJSONObjectおよびJSONArrayを使用して、解析されたJSONObjectへの低レベルのアクセスをサポートします。
<dependency>
<groupId>org.codehaus.jettison</groupId>
<artifactId>jettison</artifactId>
<version>1.3.8</version>
</dependency>
例えば:
{
"A": "a value",
"B": "another value"
}
@POST
@Path("/")
@Consumes(MediaType.APPLICATION_JSON)
public void doStuff(JSONObject json) {
/* extract data values using DOM-like API */
String a = json.optString("A");
Strong b = json.optString("B");
return;
}
その他の例については、 Jersey documentation を参照してください。
これにより、未加工の投稿にアクセスできます。
@POST
@Path("/")
@Consumes("text/plain")
@Produces(MediaType.APPLICATION_JSON)
public String processRequset(String pData) {
// do some stuff,
return someJson;
}
JSONを値として持つパラメーターを使用して、form/HTTP.POSTを送信/ POSTします。
@QueryParam jsonString
public desolveJson(jsonString)