通常开发情况下,后台一般会给出约定好的格式:
{
"code": 200,
"msg": "成功",
"data": {}
}
但是,有些后台开发者,根本不管前台开发方便与否,自成一体的风格,不按约定成俗的格式规范,返回的格式不统一,data 可能是空数组,空JSON , 字符串等,如果不做处理,会出现JSON 解析时异常(com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 4 column 14 path $.data),所以我们只能自定义转换器,对JSON 数据进行处理.
1. 定义一个 ApiResponse 基类
public class ApiResponse {
private int code;
private String msg;
private T data;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
2. 自定义响应体转换器 CustomResponseConverter 继承 Converter
public class CustomResponseConverter implements Converter {
private final Gson gson;
private TypeAdapter adapter;
private Type mType;
CustomResponseConverter(Gson gson, TypeAdapter mAdapter, Type mType) {
this.gson = gson;
this.adapter = mAdapter;
this.mType = mType;
}
@Override
public T convert(ResponseBody value) throws IOException {
ApiResponse response = new ApiResponse();
try {
String body = value.string();
JSONObject json = new JSONObject(body);
int ret = json.optInt("code");
String msg = json.optString("msg", "");
if (ret == 200) {
return gson.fromJson(body, mType);
} else {
response.setCode(ret);
response.setMsg(msg);
response.setData(json.opt("data"));
return (T) response;
}
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
} finally {
value.close();
}
}
}
3. 自定义转换工厂类 CustomGsonConverterFactory 继承 Converter.Factory
public final class CustomGsonConverterFactory extends Converter.Factory {
public static CustomGsonConverterFactory create() {
return create(new Gson());
}
public static CustomGsonConverterFactory create(Gson gson) {
return new CustomGsonConverterFactory(gson);
}
private final Gson gson;
private CustomGsonConverterFactory(Gson gson) {
if (gson == null) throw new NullPointerException("gson == null");
this.gson = gson;
}
@Override
public Converter responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
TypeAdapter> adapter = gson.getAdapter(TypeToken.get(type));
return new CustomResponseConverter<>(gson, adapter, type);
}
@Nullable
@Override
public Converter, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations,
Annotation[] methodAnnotations, Retrofit retrofit) {
return super.requestBodyConverter(type, parameterAnnotations, methodAnnotations, retrofit);
}
4. 在构造Retrofit 对象时添加 自定义转换器
ApiServer mAPIService = new Retrofit.Builder()
.client(mOkHttpClient)
.baseUrl("https://raw.githubusercontent.com/")
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
// 添加自定义转换器
.addConverterFactory(CustomGsonConverterFactory.create())
.build()
.create(ApiServer.class);
5. 现在就可以定义成功返回时的实体类 接口。
public interface ApiServer {
@GET("getUserInfo")
Observable> getInfo();
}