前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >简单对比下 Moshi 和 Kotlinx.serialization

简单对比下 Moshi 和 Kotlinx.serialization

作者头像
bennyhuo
发布2020-02-20 13:28:13
2.4K0
发布2020-02-20 13:28:13
举报
文章被收录于专栏:Bennyhuo

上一篇我们对比介绍了 Gson 和 Kotlinx.serialization,很多小伙伴在后台留言说,moshi 呢?

Moshi 怎么解决 Kotlin 数据类的问题?

首先必须说的是,Moshi 这个框架也算是 Jake 大神的良心之作了,无论从功能上,还是从使用的角度,这个框架值得推荐。

我们上一篇文章提到 Gson 不认识 Kotlin,所以对 Kotlin 的数据类几乎没有支持,这包括构造器的默认值、初始化逻辑的调用等等,而 Moshi 则类似于 Kotlinx.serialization,为我们解决了这一问题。

其实如果我们不看 Moshi 和 KS 的实现,我们单纯猜测他们要如何解决这一难题的话,无非就是使用 Kotlin 反射或使用注解处理器等方法来获取到 Kotlin 类的主构造器,以及它的参数类型和参数名(注意Kotlin反射是可以获取到参数名的哦~当然如果你用了混淆,那么这里会有问题),所以对于下面的情况:

代码语言:javascript
复制
data class Data(val id: Int, val name: String, val age: Int)

即便我们的 Json 中 K-V 的顺序是乱序的:

代码语言:javascript
复制
{"name": "bennyhuo", "id": 1000, "age": 20}

使用 Kotlin 反射,一样可以正确的将 Json 的数据结构与 Data 的主构造器的参数一一正确对应。使用注解处理器那就更不用说了。Moshi 的解决方法就是这样,它为我们提供了两种选择,你可以选择使用 Kotlin 反射,那样的话你需要忍受 Kotlin 反射 2.5M 的 jar 包以及相对较慢的运行时开销;你也可以选择注解处理器的方式,

代码语言:javascript
复制
@JsonClass(generateAdapter = true)
data class Data(val id: Int, val name: String, val age: Int)

Moshi 可以为前面的 Data 生成一个 Adapter

代码语言:javascript
复制
class DataJsonAdapter(moshi: Moshi) : JsonAdapter<Data>() {
    private val options: JsonReader.Options = JsonReader.Options.of("id", "name", "age")
    ...
    override fun fromJson(reader: JsonReader): Data {
        var id: Int? = null
        var name: String? = null
        var age: Int? = null
        reader.beginObject()
        while (reader.hasNext()) {
            when (reader.selectName(options)) {
                0 -> id = intAdapter.fromJson(reader) ?: throw JsonDataException("Non-null value 'id' was null at ${reader.path}")
                1 -> name = stringAdapter.fromJson(reader) ?: throw JsonDataException("Non-null value 'name' was null at ${reader.path}")
                2 -> age = intAdapter.fromJson(reader) ?: throw JsonDataException("Non-null value 'age' was null at ${reader.path}")
                -1 -> {
                    // Unknown name, skip it.
                    reader.skipName()
                    reader.skipValue()
                }
            }
        }
        reader.endObject()
        var result = Data(
                id = id ?: throw JsonDataException("Required property 'id' missing at ${reader.path}"),
                name = name ?: throw JsonDataException("Required property 'name' missing at ${reader.path}"),
                age = age ?: throw JsonDataException("Required property 'age' missing at ${reader.path}"))
        return result
    }

    override fun toJson(writer: JsonWriter, value: Data?) {
        ...
    }
}

大家可以自己试一试,考虑篇幅我只保留了 fromJson 的实现,大家可以参考。

Kotlin.serialization 怎么解决 Kotlin 数据类的问题?

那么同样的问题我们再问一问 KS。KS 的思路实际上与 Moshi 的注解处理器类似,只不过它因为更靠近 Kotlin 官方,是嫡系,因此它可以把一些工作放到编译器里面做。

代码语言:javascript
复制
@Serializable
data class Data(val id: Int, val name: String, val age: Int)

同样用 Data 这个类为例,我们按照 KS 的要求配置好之后,编译,我们可以在 Data 的字节码当中找到一些额外的东西:

代码语言:javascript
复制
public static final class $serializer implements KSerializer {
  public static final Data.$serializer INSTANCE;
  private static final KSerialClassDesc $$serialDesc;

  public Data update(@NotNull KInput input, @NotNull Data old) { ... }
  public Object update(KInput var1, Object var2) { ... }
  public KSerialClassDesc getSerialClassDesc() { ... }
  public void save(@NotNull KOutput output, @NotNull Data obj) { ... }
  public Data load(@NotNull KInput input) { ... }
  ...
}

$serializer 就是 KS 为 Data 生成的默认的序列化类,这样的做法其实与注解处理器有异曲同工之妙,只不过直接生成字节码的方式可以修改原有的类,因此作为 Data 的内部类, $serializer 可以访问 Data 的私有成员(如果有的话)。

Moshi 和 Kotlin.serialization 的对比

这二者从能力上,对 Kotlin 的支持其实差异不大,下面我简单它们适合的场景。

  • KS 的优势是支持 Kotlin 的 Multiplatform,对于需要多平台移植的 Kotlin 代码,使用 KS 显然更合适。
  • Moshi 的优势是兼容 Java ,毕竟 Kotlin 的代码 90% 仍然跑在 Jvm 甚至 Android 上,所以如果你的 Kotlin 代码与 Java 代码混合运行在 Jvm 上面,那么考虑使用 Moshi。

对啦,我的 Kotlin 新课 “基于 GitHub App 业务深度讲解 Kotlin1.2高级特性与框架设计” 上线之后,大家普遍反映有难度,有深度,如果哪位朋友想要吊打 Kotlin,不妨来看看哦!

https://coding.imooc.com/class/232.html

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-09-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Kotlin 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Moshi 怎么解决 Kotlin 数据类的问题?
  • Kotlin.serialization 怎么解决 Kotlin 数据类的问题?
  • Moshi 和 Kotlin.serialization 的对比
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档