美文网首页
Retrofit怎么返回一个JSON字符串?

Retrofit怎么返回一个JSON字符串?

作者: 望北8261 | 来源:发表于2023-11-26 02:22 被阅读0次
    广州发射塔

    项目用已经使用了 Retrofit,定义了接口方法,返回了 JSON 转换后的实体对象,炒鸡方便。但是总有意料之外的时候,比如我不需要返回实体对象,我要返回纯纯的 JSON 字符串,怎么办呢?

    先看源码

    通过一系列的源码分析,最后定位到 OkHttpCall 中的 parseResponse() 方法:
    下面代码中的 parseResponse 方法是纯复制过来的,没改过,可以看出当接口返回正确的数据之后,无论如何都会调用 T body = responseConverter.convert(catchingBody),把 JSON 字符串转换成了一个 T 对象,我们没有办法通过配置什么东西来实现我们要返回纯 JSON 字符串的需求,所以要想其他办法。两个办法:1、让它转,我们再转回来;2、我们自己定义怎么转。

    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 后再转 JSON 字符串

    这个很简单,我们把返回实体类改成 JSONObject,然后 Converter 会帮忙我们转成 JSONObject,然后我们再转成字符串即可。缺点就是转了两轮。

    // 接口定义
    @POST("xxx")
    fun fetch(@Body param: RequestBody): Call<JSONObject>
    
    // 使用
    val response = api.fetch(param).execute()
    val json = response.body()?.toJSONString() ?: ""
    

    方法二:自定义 Converter

    模仿 FastJsonResponseBodyConverter 自定义一个 Converter,直接返回字符串,不转实体对象,即可,收工。

    // 自定义Converter
    // 挖坑:理论上可以定义一个注解,然后判断 annotations 中是否包含此注解,
    // 如果包含,则返回自定义Converter,否则返回原来的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() ?: ""
    

    相关文章

      网友评论

          本文标题:Retrofit怎么返回一个JSON字符串?

          本文链接:https://www.haomeiwen.com/subject/fsqawdtx.html