前排提示
格式不规范 同事两行泪
接口请求成功的返回格式是
{
"ret": 0,
"msg": "ok",
"data": {
"status": 1,
"msg": "",
"type": "5"
}
}
接口请求失败的返回格式是
{
"ret": 1,
"msg": "设备不存在",
"data": [ ]
}
在"data"上一个是对象,一个是数组,如果不注意,使用了插件转成的JavaBean,那么当接口请求返回失败时,使用retrofit+rxjava+gson做的接口转换时,就会出现异常,因为[]不能转换成object;
这种情况下,后端愿意改那就很好办了,如果知错不改,又懒得去理论,就得自己改了
首先对成功结果的格式生成Java对象:
public class BeiDeviceTypesBean {
/**
* ret : 0
* data : {"status":1,"msg":"---!","type":"1"}
*/
public int ret;
public String msg;
@Nullable
public DataBean data;
public static class DataBean {
/**
* status : 1
* msg : ---!
* type : 1
*/
public int status;
public String msg;
public String type;
}
}
根据Gson的文档,传入自定义解析是实现这个JsonDeserializer接口
public class BeiDeviceTypesBeanDeserializer implements JsonDeserializer<BeiDeviceTypesBean> {
/**
* 扫描成功格式 {"ret":0,"msg":"ok","data":{"status":1,"msg":"","type":"5"}}
* 扫描失败格式 {"ret":1,"msg":"设备不存在","data":[]}
* 格式不规范 同事两行泪
*/
@Override
public BeiDeviceTypesBean deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
if (json.isJsonObject()) {
final BeiDeviceTypesBean result = new BeiDeviceTypesBean();
final JsonObject jsonObject = (JsonObject) json;
result.ret = jsonObject.get("ret").getAsInt();
result.msg = jsonObject.get("msg").getAsString();
final JsonElement data = jsonObject.get("data");
if (data != null && data.isJsonObject()) {
try {
result.data = new Gson().fromJson(data.toString(), BeiDeviceTypesBean.DataBean.class);
} catch (JsonSyntaxException e) {
result.data = null;
}
} else {
result.data = null;
}
return result;
}
return null;
}
}
在解析中 判断"data"对应的对象是否不为空且是isJsonObject,即以{}包裹的,如果为空或者不是对象的,直接丢弃,否则再进行解析;
如何进行校验,只需要在外部的Gson中传入相应的JsonDeserializer即可,如下:
final Gson mGson = new GsonBuilder()
.registerTypeAdapter(BeiDeviceTypesBean.class, new BeiDeviceTypesBeanDeserializer())
.create();
然后对text使用
mGson.fromJson(text, BeiDeviceTypesBean.class);
即可。完整的单元测试代码如下:
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class BeiDeviceTypesBeanDeserializerTest {
private Gson mGson;
@Before
public void setUp() throws Exception {
mGson = new GsonBuilder()
.registerTypeAdapter(BeiDeviceTypesBean.class, new BeiDeviceTypesBeanDeserializer())
.create();
}
@After
public void tearDown() throws Exception {
mGson = null;
}
/**
* 测试成功格式
* {"ret":0,"msg":"ok","data":{"status":1,"msg":"","type":"5"}}
*/
@Test
public void testOkText() {
final String text = "{\"ret\":0,\"msg\":\"ok\",\"data\":{\"status\":1,\"msg\":\"\",\"type\":\"5\"}}";
final BeiDeviceTypesBean result = mGson.fromJson(text, BeiDeviceTypesBean.class);
System.out.println(result);
}
/**
* 测试失败格式
* {"ret":1,"msg":"设备不存在","data":[]}
*/
@Test
public void testFailText() {
final String text = "{\"ret\":1,\"msg\":\"设备不存在\",\"data\":[]}";
final BeiDeviceTypesBean result = mGson.fromJson(text, BeiDeviceTypesBean.class);
System.out.println(result);
}
}
经验证,都解析出了符合预期的结果。如果把
registerTypeAdapter(BeiDeviceTypesBean.class, new BeiDeviceTypesBeanDeserializer())
这一行注释掉,再试试呢
如果要集成到retrofit+rxJava+gson中,应该是在这里设置
final Gson gson = new GsonBuilder()
.registerTypeAdapter(BeiDeviceTypesBean.class, new BeiDeviceTypesBeanDeserializer())
.create();
final Retrofit retrofit = new Retrofit.Builder().baseUrl(this.baseUrl)
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(getOkHttpClient())
.build();
仅供参考
网友评论