ジャージーで構築され、AppEngineにデプロイされたRESTサービスがあります。RESTサービスは、application/json
メディアタイプを消費する動詞PUTを実装します。データバインディングはJacksonによって実行されます。
動詞は、JSONで次のように表される企業と部門の関係を消費します
{"name":"myEnterprise", "departments":["HR","IT","SC"]}
クライアント側では、gsonを使用してJSON表現をJavaオブジェクトに変換します。次に、オブジェクトをRESTサービスに渡すと、正常に機能します。
問題:
JSON表現のコレクションにアイテムが1つしかない場合
{"name":"myEnterprise", "departments":["HR"]}
サービスはオブジェクトを逆シリアル化できません。
ATTENTION: /enterprise/enterprise: org.codehaus.jackson.map.JsonMappingException:
Can not deserialize instance of java.util.ArrayList out of VALUE_STRING token at
[Source: org.mortbay.jetty.HttpParser$Input@5a9c5842; line: 1, column: 2
他のユーザーから報告されているように、解決策はフラグを追加することですACCEPT_SINGLE_VALUE_AS_ARRAY
(たとえば、Jersey:ArrayListのインスタンスをStringから逆シリアル化することはできません)。ObjectMapper
それにもかかわらず、サービス側ではジャクソンによって透過的に作成されているため、私は制御していません。
質問:
ObjectMapper
有効にするようにサービス側でを構成する方法はありますACCEPT_SINGLE_VALUE_AS_ARRAY
か?注釈?web.xml
?
コードの詳細
Javaオブジェクト:
@XmlRootElement
public class Enterprise {
private String name;
private List<String> departments;
public Enterprise() {}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<String> getDepartments() {
return departments;
}
public void setDepartments(List<String> departments) {
this.departments = departments;
}
}
RESTサービス側:
@PUT
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Path("/enterprise")
public Response putEnterprise(Enterprise enterprise,
@Context HttpServletRequest req){
...
}
クライアント側:
...
String jsonString = "{\"name\":\"myEnterprise\", \"departments\":[\"HR\"]}";
Enterprise enterprise = gson.fromJson(jsonString, Enterprise.class);
System.out.println(gson.toJson(enterprise));
response = webResource
.type(MediaType.APPLICATION_JSON)
.put(ClientResponse.class,enterprise);
if (response.getStatus() >= 400) {
throw new RuntimeException("Failed : HTTP error code : " + response.getStatus());
}
...