Retrofit请求返回String报错问题解决方案

项目场景

会有这种情况,需要获取到服务端返回的字符串,再根据返回的结果进一步处理,而不是直接获取到定义好的对象。

问题描述

如果将接口定义为如下情况,当接口返回结果为大括号开头,可能会遇到报错:Expected a string but was BEGIN_OBJECT at line 1 column 2 path $

interface Service {
    @POST("/test")
    suspend fun test(@Body body: RequestBody): String
}

解决方案

这里提供两种解决方案供参考:

方案1:

将返回结果改为 JsonObject

interface Service {
    @POST("/test")
    suspend fun test(@Body body: RequestBody): JsonObject
}

方案2:

替换GsonConverterFactory(这个方案也很简单,分以下三步)

Okhttp获取请求后,通过 GsonConverterFactory 的 responseBodyConverter 获取到GsonResponseBodyConverter对象,GsonResponseBodyConverter的convert方法负责将获取到的结果转换为想要的对象。

第一步:我们这里只需要 GsonConverterFactory  和 GsonResponseBodyConverter 复制一份出来,修改一个喜欢的名字,比如我这里定义为 MyGsonConverterFactory 和 MyGsonResponseBodyConverter。

第二部:修改MyGsonResponseBodyConverter的convert方法如下:

final class MyGsonRequestBodyConverter<T> implements Converter<T, RequestBody> {

  private final Gson gson;
  private final TypeAdapter<T> adapter;

  GsonRequestBodyConverter(Gson gson, TypeAdapter<T> adapter) {
    this.gson = gson;
    this.adapter = adapter;
  }

  @Override
  public RequestBody convert(T value) throws IOException {
    String response = value.string();
        try {
            T result = gson.fromJson(response, type);
            return result;
        } catch (JsonSyntaxException e) {
            // 解析出错,如果是String类型直接返回
            if (type instanceof Class) {
                Class<?> clazz = (Class<?>) type;
                if (clazz == String.class) {
                    return (T) response;
                }
            }
            throw e;
        }
  }
}

第三部:

实例化Service的时候记得替换成我们定义的ConverterFactory

Retrofit
    .Builder()
    .baseUrl(hostUrl)
    .client(okHttpClient)
    .addConverterFactory(MyGsonConverterFactory.create()) // 自定义的ConvertFactory

猜你喜欢

转载自blog.csdn.net/u012218652/article/details/125739448