美文网首页
gson自定义解析

gson自定义解析

作者: 100个大西瓜 | 来源:发表于2023-07-09 17:06 被阅读0次

    前排提示
    格式不规范 同事两行泪
    接口请求成功的返回格式是

    {
        "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();
    

    仅供参考

    相关文章

      网友评论

          本文标题:gson自定义解析

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