使用Retrofit发送json数据时被转义的解决方案

记录一下在使用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> 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> call = apiService.getObjectFromPost(jsonData);

call.enqueue(new Callback>() {
	@Override
	public void onResponse(@NonNull Call> call, @NonNull Response> response) {
		try {
			Result result = response.body();
			if (result != null) {
				showResult(result.toString());
			}
		} catch (Exception e) {
			showResult("Fail : " + e.getLocalizedMessage());
		}
	}

	@Override
	public void onFailure(@NonNull Call> 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> 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> call = apiService.getObjectFromPost(requestBody);

call.enqueue(new Callback>() {
	@Override
	public void onResponse(@NonNull Call> call, @NonNull Response> response) {
		try {
			Result result = response.body();
			if (result != null) {
				showResult(result.toString());
			}
		} catch (Exception e) {
			showResult("Fail : " + e.getLocalizedMessage());
		}
	}

	@Override
	public void onFailure(@NonNull Call> call, @NonNull Throwable t) {
		showResult("onFailure : " + t.getLocalizedMessage());
	}
});

ok了,Json字符串被转义的问题已经解决。

PS :如果您有更好的处理方式或者建议,欢迎您留言、指正和讨论

本文的参考链接:

1.https://stackoverflow.com/questions/35747524/retrofit-2-content-type-issue#

2.https://blog.csdn.net/zhupumao/article/details/51628698

你可能感兴趣的:(android,基础知识,网络框架)