Gson解析在Kotlin下有什么问题?
忽略了data class的null safty检查和默认值。
为什么Gson会忽略data class的null safty检查和默认值?
在Gson的ReflectiveTypeAdapterFactory中调用了ConstructorConstructor.get()。
在这里Gson 实例化对象分为四种情况:
- 使用我们自定义的 InstanceCreator,可以在初始化时加入它;
- 使用默认构造器,也就是无参构造函数;
- 如果是 Collection 或 Map,则返回对应的对象;
- 使用 UnSafe。
如果没有无参构造函数就用UnSafe去构造对象。
UnSafe去构造对象,会绕过构造函数,只会在堆中去分配一个对象实例。
如果仅对data class的部分字段设置了默认值,而不是所有字段设置默认,是不会生成无参构造函数的。
解决方案
想办法提供一个无参构造函数。
- 构造函数中的所有变量都设置默认值
- 手动写一个无参构造函数。
- 字段声明在类的内部,就会自动无参构造函数了。
改写data class不太合适,这样的方式不够自动化,无法做出客观的保证。
最好的方式是对Gson做改进,因为引入新的库可能所有序列化的地方都要改。
有哪些库解析data class没有问题?
moshi和kotlinx.serialization。
moshi的解决方案有两种:
- 引入kotlin反射库,包体积会增大2.5MB。
- 编译时通过注解处理器为每个data class生成JsonAdapter去解析Json数据。
kotlinx.serialization解决方案:
- 通过在data class上添加注解,编译时通过注解处理器来处理。
Gson可以解决这些问题吗?
可以把moshi的解决方案在gson里实现一下是比较适合的,改造需要动用不少代码。如果改动太大就是直接用moshi了。
Moshi 和 Kotlin.serialization 的对比:
两者对 Kotlin 的支持差异不大。
- KS 的优势是支持 Kotlin 的 Multiplatform,对于需要多平台移植的 Kotlin 代码,使用 KS 更合适,但不兼容Java。
- Moshi 的优势是兼容 Java 。
所以如果是 Kotlin 与 Java 混编,考虑使用 Moshi。