0%

Gson在Kotlin下的崩溃

Gson解析在Kotlin下有什么问题?

忽略了data class的null safty检查和默认值。

为什么Gson会忽略data class的null safty检查和默认值?

在Gson的ReflectiveTypeAdapterFactory中调用了ConstructorConstructor.get()。

在这里Gson 实例化对象分为四种情况:

  1. 使用我们自定义的 InstanceCreator,可以在初始化时加入它;
  2. 使用默认构造器,也就是无参构造函数;
  3. 如果是 Collection 或 Map,则返回对应的对象;
  4. 使用 UnSafe。

如果没有无参构造函数就用UnSafe去构造对象。

UnSafe去构造对象,会绕过构造函数,只会在堆中去分配一个对象实例。

如果仅对data class的部分字段设置了默认值,而不是所有字段设置默认,是不会生成无参构造函数的。

解决方案

想办法提供一个无参构造函数。

  1. 构造函数中的所有变量都设置默认值
  2. 手动写一个无参构造函数。
  3. 字段声明在类的内部,就会自动无参构造函数了。

改写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 的支持差异不大。

  1. KS 的优势是支持 Kotlin 的 Multiplatform,对于需要多平台移植的 Kotlin 代码,使用 KS 更合适,但不兼容Java。
  2. Moshi 的优势是兼容 Java 。

所以如果是 Kotlin 与 Java 混编,考虑使用 Moshi。

参考资料