关于kotlin serialization集成到retrofit的一些研究

前几天,我一直在找retrofit集成kotlin serialization的资料,才发现,网上的资料是真的少,如果你有幸看到这篇文章,就默默记下来。
关于为什么要急kotlin serialization的问题,相信如果你用gson发现每个属性必须要赋值才能调用到无参构造方法将默认值赋值,这个你使用kotlin 的data class时候,相信对代码追求完美的你会很难受

而使用kotlin serialization,就可以很开心的使用kotlin的特性来使用,另外在闲扯两句kotlin serialization的优势,首先,它是kotlin官方出的一套框架,结合kotlin的使用堪称完美,其次,相信你们也会关注它的解析效率,关于这个,大家都知道程序运行时,使用反射有影响效率,而它使用的是编译插件的方式, 网上的资料也都很多,有兴趣的同学可以自己去测试。

好了,现在直接上干货,在我一开始接触到这个kotlin serialization的时候,我发现每个数据类需要加上@Serializable这个注解,
就比如

@Serializable
data class InfoEntity<T>(val result:T?, val msg:String, val code:String)

@Serializable
data class ResultEntity(val name:String,val phone:String,val age:Int)

关于InfoEntity<ResultEntity>这个数据类的解析方式:

val json = Json(JsonConfiguration.Stable.copy(unquoted = true))
val result = json.parse(serializerByTypeToken(type),value.string()) as InfoEntity<ResultEntity>

看到这里,我相信你已经看懂啦,其实type 转换成KSerializer<Any>的方法呢,
就是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<T> internal constructor(
    private val type: Type
) : Converter<ResponseBody, T> {
    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<Any>然后用json.parse解析

这里可以自定义将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<Date> {
    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

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容