Kotlin使用Gson总结

4,058 阅读3分钟

json -> class 时,Gson只会使用无参构造函数,如果没有他就通过Unsafe自己创建,不会走其他构造函数。

空安全设计

首先明确一点,Gson不会管Kotlin的空安全设计。只要是Json数据里面指定的是null的数据,就算你写的是非空最后实例化出来的时候也会是空的。例如:

Kotlin

data class User(
        val age: Int = 11,
        val name: String = "lucy",
        val phone: String = "13888888888"
)

Json

"name" : null

最后实例化出来的user.name = null,而没有的字段user.phone = 13888888888 user.age = 11

使用data class的情况

必须保证所有的变量都给了默认值,这样 data class 才有无参构造函数,从而使你定义的默认值有效,如果不是全给,只要是 json 里面没有的,数据类型都为 0 ,布尔型为 false ,其他类型都是 null。例如:

Kotlin

data class User(
        val age: Int,
        val name: String = "lucy",
        val phone: String = "13888888888"
)

Json

"name" : null

由于age没有给默认值,编译的时候Kotlin就不会给这个类默认的无参构造函数,Gson就通过Unsafe自己创建,也就不会走Kotlin定义的构造函数去赋值。最后实例化出来的就是:age = 0 , name = null , phone = null

解决办法

1.Moshi

Moshi倒是能很好的支持Kotlin的空安全,但是也会有困扰,首先服务器返回的Json的数据指不定哪个就是null的,如果你代码里面设定的是非空,那Moshi就会直接抛异常,不解析了。感觉和实际开发使用有点不合,可能其他数据会有用啊,不能只因为一个异常数据导致所有的都用不了,这些判断应该放在我自己的代码里面我才安心。而且切换库有代价啊!!!

2.安全的写法
data class User(
        val age: Int,
        @SerializedName("name") private val _name: String?
) {
    val name
        get() = _name ?: "lucy"
}

像这种你不想他为空,就算是服务器错误的给了一个空值过来,你也要用一个默认值代替,可以这么写。显然,这个解决方案很冗长,如果变量多了那是要写一大把代码,我用data class不就是图方便吗,当然你不嫌麻烦可以这样写。

使用建议

所以我使用的初步建议就是,让一切都为空!!!

  • 定义类的时候必须给所有变量赋默认值,并且非数据类型都设定可空,默认赋值为空;
  • 确定Json里面不会出现,而是自己加的一些工具属性可以定义默认值。

像这样:

data class User(
        val age: Int = 0,
        val name: String? = null,
        val pay: Boolean = false,
        val phone: String = "13888888888"
)