记录一下在使用Retrofit网络框架时,遇到的问题,和在经过一番搜索后找到的解决方案。
首先大概说明一下背景:
1.Android端使用的Retrofit框架版本是2.3
2.云端是Rest API,具体实现使用的是jersey框架
再来说一下遇到的问题:简单来讲就是在终端向云端发起Post请求,请求体中携带json格式的字符串数据,在云端拦截到请求并获取这个json数据时,出现了字符被转义,导致json字符串不合法而抛出异常,转义的数据举例如下:
由终端发送的原始json字符串 : {"name":"Bob","gender":"Male"}
云端Rest API接口收到的字符串 : {\"name\":\"Bob\",\"gender\":\"Male\"}
发生这个错误时,终端的Retrofit对应的网络访问接口方法如下:
/**
* Post请求,请求体携带json数据
* 该方法属于ApiService这个Interface,为节省篇幅就只展示了方法定义,
* 为避免误会,特此说明
* @param jsonData 携带的json数据体
* @return Call a request that ready to execute
*/
@HTTP(method = "POST",path = "connect/convertObj",hasBody = true)
Call<Result<String>> getObjectFromPost(@Body String jsonData);
调用模块代码如下:
//生成Retrofit实体类
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(SERVER_BASE_URL)
.addConverterFactory(new Retrofit2ConverterFactory())
.build();
//获取网络访问接口对象
ApiService apiService = retrofit.create(ApiService.class);
//调用携带Json数据的Post请求方法
//这里的jsonData的内容是 : "{"name":"Bob","gender":"Male"}"
Call<Result<String>> call = apiService.getObjectFromPost(jsonData);
call.enqueue(new Callback<Result<String>>() {
@Override
public void onResponse(@NonNull Call<Result<String>> call, @NonNull Response<Result<String>> response) {
try {
Result<String> result = response.body();
if (result != null) {
showResult(result.toString());
}
} catch (Exception e) {
showResult("Fail : " + e.getLocalizedMessage());
}
}
@Override
public void onFailure(@NonNull Call<Result<String>> call, @NonNull Throwable t) {
showResult("onFailure : " + t.getLocalizedMessage());
}
});
在云端的API接口调试过程中发现,发送的json数据到云端时已经发生转义,如上文所述。
解决方案
经过翻阅Stack Overflow和csdn上面的诸位大神的指导意见,需要将终端的代码修改如下
/**
* Post请求,请求体携带json数据
* 参数类型从String,改为RequestBody
* 添加请求头的注解,并指定content type为json格式
* @param bodyWithJsonData 携带数据的请求体
* @return Call a request that ready to execute
*/
@HTTP(method = "POST",path = "connect/convertObj",hasBody = true)
@Headers("Content-Type:application/json;charset=utf-8")
Call<Result<String>> getResFromPostWithGsonConvertToObject(@Body RequestBody bodyWithJsonData);
调用方法的核心代码修改如下:
//生成Retrofit实体类
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(SERVER_BASE_URL)
.addConverterFactory(new Retrofit2ConverterFactory())
.build();
//获取网络访问接口对象
ApiService apiService = retrofit.create(ApiService.class);
//指定content type为json类型
final MediaType CONTENT_TYPE = MediaType.parse("application/json");
RequestBody requestBody = RequestBody.create(CONTENT_TYPE,jsonString);
//调用携带Json数据的Post请求方法
//发送整个RequestBody,而不是字符串类型的数据
Call<Result<String>> call = apiService.getObjectFromPost(requestBody);
call.enqueue(new Callback<Result<String>>() {
@Override
public void onResponse(@NonNull Call<Result<String>> call, @NonNull Response<Result<String>> response) {
try {
Result<String> result = response.body();
if (result != null) {
showResult(result.toString());
}
} catch (Exception e) {
showResult("Fail : " + e.getLocalizedMessage());
}
}
@Override
public void onFailure(@NonNull Call<Result<String>> call, @NonNull Throwable t) {
showResult("onFailure : " + t.getLocalizedMessage());
}
});
ok了,Json字符串被转义的问题已经解决。
PS :如果您有更好的处理方式或者建议,欢迎您留言、指正和讨论
本文的参考链接:
1.https://stackoverflow.com/questions/35747524/retrofit-2-content-type-issue#