前几天,我一直在找retrofit集成kotlin serialization的资料,才发现,网上的资料是真的少,如果你有幸看到这篇文章,就默默记下来。
关于为什么要急kotlin serialization的问题,相信如果你用gson发现每个属性必须要赋值才能调用到无参构造方法将默认值赋值,这个你使用kotlin 的data class时候,相信对代码追求完美的你会很难受
而使用kotlin serialization,就可以很开心的使用kotlin的特性来使用,另外在闲扯两句kotlin serialization的优势,首先,它是kotlin官方出的一套框架,结合kotlin的使用堪称完美,其次,相信你们也会关注它的解析效率,关于这个,大家都知道程序运行时,使用反射有影响效率,而它使用的是编译插件的方式, 网上的资料也都很多,有兴趣的同学可以自己去测试。
好了,现在直接上干货,在我一开始接触到这个kotlin serialization的时候,我发现每个数据类需要加上@Serializable这个注解,
就比如
@Serializable
data class InfoEntity(val result:T?, val msg:String, val code:String)
@Serializable
data class ResultEntity(val name:String,val phone:String,val age:Int)
关于InfoEntity
val json = Json(JsonConfiguration.Stable.copy(unquoted = true))
val result = json.parse(serializerByTypeToken(type),value.string()) as InfoEntity
看到这里,我相信你已经看懂啦,其实type 转换成KSerializer
就是serializerByTypeToken(type)方法,然后就可以愉快的使用json.parse方法解析啦
下面的东西就简单啦,retrofit的转换类ResponseBodyConverter啦
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonConfiguration
import kotlinx.serialization.serializerByTypeToken
import okhttp3.ResponseBody
import retrofit2.Converter
import java.io.IOException
import java.lang.reflect.Type
class JsonResponseBodyConverter internal constructor(
private val type: Type
) : Converter {
private val json = Json(JsonConfiguration.Stable.copy(unquoted = true))
@Suppress("UNCHECKED_CAST")
@Throws(IOException::class)
override fun convert(value: ResponseBody): T = value.use {
json.parse(serializerByTypeToken(type),value.string()) as T
}
}
这里呢,也要提一句github上的项目[retrofit2-kotlinx-serialization-converter],如果没有特殊的需求,可以直接引用
implementation 'com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:0.4.0'
val contentType = MediaType.get("application/json")
val retrofit = Retrofit.Builder()
.baseUrl("https://example.com/")
.addConverterFactory(Json.asConverterFactory(contentType))
.build()
其实如果打开源码,其实也是使用serializerByTypeToken(type)转换成KSerializer
这里可以自定义将string的类型转换为Date时间类
//{"id":10,"time":"11/01/2001 10:24:14.145"}
@Serializable
data class Result(
val id: Int,
@Serializable(with=DateSerializer::class) val time: Date
)
@Serializer(forClass = Date::class)
object DateSerializer: KSerializer {
private val df: DateFormat = SimpleDateFormat("dd/MM/yyyy HH:mm:ss.SSS")
override val descriptor: SerialDescriptor =
StringDescriptor.withName("WithCustomDefault")
override fun serialize(encoder: Encoder, obj: Date) {
encoder.encodeString(df.format(obj))
}
override fun deserialize(decoder: Decoder): Date {
return df.parse(decoder.decodeString())
}
}
今天就讲到这里啦,其他更多自定义介绍可以直接去github的介绍里面看
https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/custom_serializers.md