Android Retrofit 自定义GsonConverterFactory

在项目开发中,后台返回的格式没有统一返回格式(成功和失败的返回格式不一致)。
案例说明:
登录业务json(成功时)

{
    "code": 0,
    "message": "登录成功",
    "data": {
        "name": "admin",
        "token": "ad987810544564310"
    }
}

登录业务json(失败时)

{
    "code": 0,
    "message": "登录成功",
    "data": ""      
}

细心的朋友可能已经发现了问题所在。成功的时候返回的Object,而失败的时候返回的String。这样就会造成json解析异常了。我们一般的配置Retrofit如下所示。

  Retrofit retrofit = new Retrofit.Builder()
                .client(getOkHttpClient())
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .baseUrl(BASE_URL)
                .build();

GsonConverterFactory这个类解析失败,就会造成错误了。所有我们要自定义GsonConverterFactory类来解决上面的问题。

1、MyGsonConverterFactory类
public class MyGsonConverterFactory extends Converter.Factory {

  public static MyGsonConverterFactory create() {
    return create(new Gson());
  }


  @SuppressWarnings("ConstantConditions") // Guarding public API nullability.
  public static MyGsonConverterFactory create(Gson gson) {
    if (gson == null) throw new NullPointerException("gson == null");
    return new MyGsonConverterFactory(gson);
  }

  private final Gson gson;

  private MyGsonConverterFactory(Gson gson) {
    this.gson = gson;
  }

  @Override
  public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
      Retrofit retrofit) {
    TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
    return new MyGsonResponseBodyConverter<>(gson, adapter);
  }

  @Override
  public Converter<?, RequestBody> requestBodyConverter(Type type,
      Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
    TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
    return new MyGsonRequestBodyConverter<>(gson, adapter);
  }
}
2、MyGsonRequestBodyConverter类
public class MyGsonRequestBodyConverter<T> implements Converter<T, RequestBody> {
  private static final MediaType MEDIA_TYPE = MediaType.get("application/json; charset=UTF-8");
  private static final Charset UTF_8 = Charset.forName("UTF-8");

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

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

  @Override public RequestBody convert(T value) throws IOException {
    Buffer buffer = new Buffer();
    Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8);
    JsonWriter jsonWriter = gson.newJsonWriter(writer);
    adapter.write(jsonWriter, value);
    jsonWriter.close();
    return RequestBody.create(MEDIA_TYPE, buffer.readByteString());
  }
}
3、MyGsonResponseBodyConverter类
// 方法一
public class MyGsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
    private final Gson gson;
    private final TypeAdapter<T> adapter;

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

    @Override
    public T convert(ResponseBody value) throws IOException {

        String json = value.string();
        //第一次解析
        BaseBean obj = GsonUtils.json2Bean(json, BaseBean.class);
        if (!obj.isSuccess()) {
            //如果是服务端返回的错误码,则抛出自定义异常
            throw new ApiException(obj.getStatus(), obj.getMsg());
        }
        //第二次解析
        T  result = adapter.fromJson(json);
        value.close();
        return result;


        //原生的代码(RxJava中的代码)
//        JsonReader jsonReader = gson.newJsonReader(value.charStream());
//        try {
//            T result = adapter.read(jsonReader);
//            if (jsonReader.peek() != JsonToken.END_DOCUMENT) {
//                throw new JsonIOException("JSON document was not fully consumed.");
//            }
//            return result;
//        } finally {
//            value.close();
//        }
    }
}

// 方法二
public class BaseResponse{
    public int code;
    public String msg;
}

final class MyGsonResponseBodyConverter<T> implements Converter<ResponseBody, Object> {

    private final TypeAdapter<T> adapter;

    GsonResponseBodyConverter(TypeAdapter<T> adapter) {
        this.adapter = adapter;
    }

    @Override
    public Object convert(ResponseBody value) throws IOException {
        try {
            BaseResponse response = (BaseResponse) adapter.fromJson(value.charStream());
            if (response.getCode() == 200) {
                // success
                return response.getResults();
            } else {
                // 特定 API 的错误,在相应的 onError 的方法中进行处理
                throw new ApiException(response.getCode(), response.getMessage());
            }
        } finally {
            value.close();
        }

        return null;
    }
}
调用方式
 Retrofit retrofit = new Retrofit.Builder()
                .client(getOkHttpClient())
//                .addConverterFactory(GsonConverterFactory.create())   //替换调之前的,采用下面的方式即可
                .addConverterFactory(MyGsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .baseUrl(BASE_URL)
                .build();
另外附上json解析工具类:
public class GsonUtils {

    private static Gson mGson = new Gson();

    public static <T> T json2Bean(String json, Class<T> clazz) {
        try {
            return mGson.fromJson(json, clazz);
        } catch (Exception e) {
            LogUtils.e("GsonUtils:"+e.toString());
            return null;
        }
    }
 }

————————————————
转载于:https://blog.csdn.net/weixin_42273922/article/details/105947197

猜你喜欢

转载自blog.csdn.net/weixin_42602900/article/details/133771318