Retrofit怎么返回一個(gè)JSON字符串?

廣州發(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() ?: ""
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容