在POST中使用重音字符时,Spring返回400

时间:2015-02-01 04:26:30

标签: android json spring-mvc jackson

问题:

当从Android应用程序发送POST请求时,重音字符会导致Jackson在对象映射阶段失败,但在使用适用于chrome的Advanced Rest Client插件时工作正常。

这让我相信这个问题与Android代码发送请求的方式有关,但我尝试添加对UTF-8的显式引用但没有成功。当我在执行期间调试过程时,所有值都是正确的。

上下文:

我在Android上开发了一个应用程序,它连接到一个公开在Spring中实现的端点的服务器。该服务器使用Spring MVC开发,并使用Google App Engine。

特定端点可以接收用户输入的值,其中可以包括重音字符。

有效负载遵循此结构,映射到服务器端的对象:

{
    "senderEmail":"<email here>",
    "token":"<token here>",
    "friendList":["<email here>"],
    "base64Value":"<base64 encoded value here>",
    "message":"ú"
}

当从REST客户端发送此有效负载时,服务器处理请求并返回200.从Android应用程序发送时,会引发以下异常:

org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver resolveException: Resolving exception from handler [public org.springframework.http.ResponseEntity<java.lang.Object> com.web.controllers.PictureController.postPic(com.web.controllers.viewobjects.PostPicRequest)]: org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: Invalid UTF-8 middle byte 0x22
     at [Source: com.google.apphosting.runtime.jetty.RpcConnection$RpcRequestInput@832f7f; line: 1, column: 15] (through reference chain: com.web.controllers.viewobjects.PostPicRequest["message"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Invalid UTF-8 middle byte 0x22
     at [Source: com.google.apphosting.runtime.jetty.RpcConnection$RpcRequestInput@832f7f; line: 1, column: 15] (through reference chain: com.web.controllers.viewobjects.PostPicRequest["message"])

代码:

发送请求的Android代码(已编辑以供公众查看):

URL url = new URL( URL_POST );
urlConnection = (HttpURLConnection)url.openConnection();
urlConnection.setRequestMethod("POST");
urlConnection.setRequestProperty("Content-Type", "application/json");
urlConnection.setRequestProperty("Accept-Encoding", ""); 

String base64Value = "blabla"

//Get JSON
JSONObject jsonObject = new JSONObject();
jsonObject.accumulate(Api.POST_PARAM_BASE64VALUE, base64Value);
jsonObject.accumulate(Api.POST_PARAM_SENDEREMAIL, senderEmail);
jsonObject.accumulate(Api.POST_PARAM_TOKEN, token);
jsonObject.accumulate(Api.POST_PARAM_MESSAGE, message);

//Make array from friends string
String[] allFriendsArray = friendList.split(",");
JSONArray friendsJsonArray = new JSONArray();
for(String x : allFriendsArray) {
    friendsJsonArray.put(x.trim());
}

jsonObject.accumulate(Api.POST_PARAM_FRIENDLIST, friendsJsonArray);
jsonObject.accumulate(Api.POST_PARAM_ISANONYMOUS, isAnonymous);

DataOutputStream wr = new DataOutputStream(urlConnection.getOutputStream());
wr.writeBytes(jsonObject.toString());
wr.flush();
wr.close();

int httpResponseCode = urlConnection.getResponseCode();

在Android中使用以下代码时得到相同的响应:

HttpPost httpPost = new HttpPost(Api.URL_POST);
httpPost.setEntity(new StringEntity(jsonObject.toString()));
httpPost.setHeader("Accept", "application/json");
httpPost.setHeader("Content-type", "application/json");
HttpResponse resp = new DefaultHttpClient().execute(httpPost);    

Spring方法定义,它包含在用@RestController注释的控制器中:

@RequestMapping(value= "/post", method = RequestMethod.POST)
public ResponseEntity<Object> post(@RequestBody PostRequest postRequest) { /*code here*/}

1 个答案:

答案 0 :(得分:0)

找到以下代码片段(here),它们正确编码了有效负载,并在服务器端也正确接收。

谢谢大家!

    OutputStream os = urlConnection.getOutputStream();
    BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));
    writer.write( jsonObject.toString() );
    writer.close();
    os.close();
    int httpResponseCode = urlConnection.getResponseCode();