
廣州發(fā)射塔
項(xiàng)目用已經(jīng)使用了 Retrofit,定義了接口方法,返回了 JSON 轉(zhuǎn)換后的實(shí)體對(duì)象,炒雞方便。但是總有意料之外的時(shí)候,比如我不需要返回實(shí)體對(duì)象,我要返回純純的 JSON 字符串,怎么辦呢?
先看源碼
通過一系列的源碼分析,最后定位到 OkHttpCall 中的 parseResponse() 方法:
下面代碼中的 parseResponse 方法是純復(fù)制過來(lái)的,沒改過,可以看出當(dāng)接口返回正確的數(shù)據(jù)之后,無(wú)論如何都會(huì)調(diào)用 T body = responseConverter.convert(catchingBody),把 JSON 字符串轉(zhuǎn)換成了一個(gè) T 對(duì)象,我們沒有辦法通過配置什么東西來(lái)實(shí)現(xiàn)我們要返回純 JSON 字符串的需求,所以要想其他辦法。兩個(gè)辦法:1、讓它轉(zhuǎn),我們?cè)俎D(zhuǎn)回來(lái);2、我們自己定義怎么轉(zhuǎn)。
final class OkHttpCall<T> implements Call<T> {
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
ResponseBody rawBody = rawResponse.body();
// Remove the body's source (the only stateful object) so we can pass the response along.
rawResponse =
rawResponse
.newBuilder()
.body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
.build();
int code = rawResponse.code();
if (code < 200 || code >= 300) {
try {
// Buffer the entire body to avoid future I/O.
ResponseBody bufferedBody = Utils.buffer(rawBody);
return Response.error(bufferedBody, rawResponse);
} finally {
rawBody.close();
}
}
if (code == 204 || code == 205) {
rawBody.close();
return Response.success(null, rawResponse);
}
ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);
try {
T body = responseConverter.convert(catchingBody);
return Response.success(body, rawResponse);
} catch (RuntimeException e) {
// If the underlying source threw an exception, propagate that rather than indicating it was
// a runtime exception.
catchingBody.throwIfCaught();
throw e;
}
}
}
方法一:返回 JSONObject 后再轉(zhuǎn) JSON 字符串
這個(gè)很簡(jiǎn)單,我們把返回實(shí)體類改成 JSONObject,然后 Converter 會(huì)幫忙我們轉(zhuǎn)成 JSONObject,然后我們?cè)俎D(zhuǎn)成字符串即可。缺點(diǎn)就是轉(zhuǎn)了兩輪。
// 接口定義
@POST("xxx")
fun fetch(@Body param: RequestBody): Call<JSONObject>
// 使用
val response = api.fetch(param).execute()
val json = response.body()?.toJSONString() ?: ""
方法二:自定義 Converter
模仿 FastJsonResponseBodyConverter 自定義一個(gè) Converter,直接返回字符串,不轉(zhuǎn)實(shí)體對(duì)象,即可,收工。
// 自定義Converter
// 挖坑:理論上可以定義一個(gè)注解,然后判斷 annotations 中是否包含此注解,
// 如果包含,則返回自定義Converter,否則返回原來(lái)的Converter。
.addConverterFactory(object : Converter.Factory() {
override fun responseBodyConverter(
type: Type,
annotations: Array<out Annotation>,
retrofit: Retrofit
): Converter<ResponseBody, String> {
return Converter<ResponseBody, String> { responseBody ->
responseBody.use { it.string() }
}
}
})
// 接口定義
@POST("xxx")
fun fetch(@Body param: RequestBody): Call<String>
// 使用
val response = api.fetch(param).execute()
val json = response.body() ?: ""