android gson插件,GitHub - vihuela/GsonPlugin: android gson 插件

本文探讨了在使用Gson处理后台PHP等弱数据类型时遇到的字段类型不匹配问题,可能导致Json解析失败。通过分析Gson的源码,提出了解决方案——利用代码插桩在解析工厂类的read方法前插入检查,如果字段不满足要求则跳过当前解析,防止整个Json解析中断。此外,还介绍了如何注册自定义的解析工厂以处理特定类型的异常。

描述

使用代码插桩,优化Gson处理后台弱数据类型字段不规范的问题

字段类型解析失败会跳过当前字段,并赋予一个不为空的默认值,不会影响后续解析,不需要业务端判空字段类型

来由

后台如果是弱数据类型,如:PHP,那么数据返回就会存在不可控,尤其后台是长周期大项目,几乎不可能为了App兼容

Android 使用Gson时为强字段类型约束,就会存在:

定义的是Int,返回String

定义的是Obejct,返回Array

定义的是Boolean,返回的是String

定义的是String,返回的是null

...

大部分情况是某个字段解析失败,导致整个Json解析失败,界面无法渲染

虽然可以使用JsonElement接收,也可以使用String接收,然后在判空、判断类型取值,但是存在大量重复代码

分析

我们拿集合解析举例:

GSON(2.8.6)会使用CollectionTypeAdapterFactory 处理 集合解析

源码73行

@Override public Collection read(JsonReader in) throws IOException {

...

in.beginArray();

...

}

public void beginArray() throws IOException {

...

throw new IllegalStateException("Expected BEGIN_ARRAY but was " + peek() + locationString());

}

}

可以看到若in.beginArray();解析异常则中断整个解析

其它解析大同小异,如

ReflectiveTypeAdapterFactory处理对象解析

TypeAdapters处理基本数据类型解析

解决

GsonBuilder提供了自定义的解析工厂registerTypeAdapter,如:

val IntDeser = JsonDeserializer { json, typeOfT, context ->

try {

json?.asInt ?: 0

} catch (e: NumberFormatException) {

0

}

}

registerTypeAdapter(Int::class.java, IntDeser)

但是目前无法处理对象类型,所以考虑使用代码插桩:

我们可以在解析工厂类的read方法之前插入代码,若不满足要求则不进去read方法,同时跳过当前解析,则可以解决字段解析抛出异常中断整个解析链的问题

使用

根build.gradle

buildscript {

repositories {

...

maven { url 'https://www.jitpack.io' }

}

dependencies {

...

classpath 'com.github.vihuela:GsonPlugin:1.3'

}

}

app的build.gradle

apply plugin: 'com.ricky.plugin.transform.gson'

dependencies {

...

implementation 'com.google.code.gson:gson:2.8.6'

}

拦截Json解析错误

GsonPluginUtil.setListener { exception, invokeStack ->

Log.e("gson:", exception)

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值