kotlinx.serialization处理Json解析

kotlinx.serialization 是什么?


Kotlin serialization consists of a compiler plugin, that generates visitor code for serializable classes, runtime library with core serialization API and JSON format, and support libraries with
ProtoBuf, CBOR and properties formats.

Kotlin官方的序列化库,具有以下特点:

  • 可以基于@serializable编译器生成序列化代码从而避免反射
  • 支持 JSONCBORProtobuf等多种格式
  • 可以用于Kotln MPP项目,支持跨平台使用

Kotlinx.serialization支持的格式很多,0.2.0开始增加了对HOCON的支持:https://github.com/Kotlin/kotlinx.serialization/blob/master/formats/README.md

Android开发中经常用到GsonJacksonMoshikotshi等Json解析库,全面转向Kotlin开发后,kotlinx.serialization 也是一个很好的选择。

gradle


root的build.gradle

buildscript {
    ext.kotlin_version = "1.3.70" // 最低v1.3.30以上

    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
    }
}

module的build.gradle

repositories {
    jcenter()
}

dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" // or "kotlin-stdlib-jdk8"
    implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.20.0"
}

也可用kts进行gradle配置,如下:

plugins {
    kotlin("multiplatform") // or kotlin("jvm") or any other kotlin plugin
    kotlin("plugin.serialization") version "1.3.70"
}
repositories {
    // artifacts are published to JCenter
    jcenter()
}

dependencies {
    implementation(kotlin("stdlib", KotlinCompilerVersion.VERSION)) // or "stdlib-jdk8"
    implementation("org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.20.0") // JVM dependency
}

proguard


proguard-rules.pro

-keepattributes *Annotation*, InnerClasses
-dontnote kotlinx.serialization.SerializationKt
-keep,includedescriptorclasses class com.yourcompany.yourpackage.**$$serializer { *; } # <-- change package name to your app's
-keepclassmembers class com.yourcompany.yourpackage.** { # <-- change package name to your app's
    *** Companion;
}
-keepclasseswithmembers class com.yourcompany.yourpackage.** { # <-- change package name to your app's
    kotlinx.serialization.KSerializer serializer(...);
}

如上,就可以在工程中使用kotlinx.serialzation了。

接下实现Json解析的代码

data class


import kotlinx.serialization.*
import kotlinx.serialization.json.*

@Serializable // 1
data class Data(
  val id: Int,
  @SerialName("user_name") // 2
  val name: String = "hoge",
  @SerialName("mail_address")
  val mailAddress: String? = "" // 3
)
  1. 为序列化对象添加@Serializable
  2. @SerialName 可以重新定义序列化时的参数名
  3. 如果数据有可能为null,则要指定为可空类型,否则序列化时会被赋值null,运行时可能出现NPE

除了以上几个常用注解外,还有@Required等其他注解满足序列化过程的其他需求

config & parse


// sample data
val json = """{"id":0,"user_name":"hoge","mail_address":"[email protected]"}"""

val obj = Json(JsonConfiguration.Stable).parse(Data.serializer(), json)

Json(....)中进行序列化的设置,JsonConfiguration.Stable是缺省设置,可以不显式指定,其定义如下:

companion object {
		@JvmStatic
        public val Stable = JsonConfiguration(
            encodeDefaults = true,
            ignoreUnknownKeys = false,
            isLenient = false,
            serializeSpecialFloatingPointValues = false,
            allowStructuredMapKeys = true,
            prettyPrint = false,
            unquotedPrint = false,
            indent = defaultIndent,
            useArrayPolymorphism = false,
            classDiscriminator = defaultDiscriminator
        )
}

可以通过查看源码了解上面各项目的具体函数以。

Stable的检查比较严格, 如果mail_address不是可空类型,但在解析时数据为空,使用Stable可以在parse时抛出error,避免运行时的NPE。Moshi也提供类似功能,处理Kotlin的空安全( Moshi兼容Kotlin空安全)

当然,也可以自定义JsonConfiguration的内容,例如

// sample data
val json = """{"id":0,"user_name":"hoge"}"""

val parsedJson = Json(
    JsonConfiguration(
       isLenient = true, // 1
       ignoreUnknownKeys = true,
       serializeSpecialFloatingPointValues = true
    )
).parse(Data.serializer(), json)

上面的配置就不会在在解析时,因为遇到非法Null值而抛出异常,但同时将风险留到了后面。

0.14.0起可以通过下面的方法处理可空的value,更加方便了

// sample data
val json = """{"id":0,"name":"hoge"}"""

val obj = Json.nonstrict.parse(Data.serializer(), json)

Moshi VS Kotlinx.serialization


最后比较一下MoshiKotlinx.serialization,这两个库都是适合在Kotlin使用的序列化库

  • KS 的优势是支持 Kotlin 的 Multiplatform,对于需要多平台移植的 Kotlin 代码,显然更合适
  • Moshi 的优势是同时兼容 Java ,所以如果你的 Kotlin 代码与 Java 代码混合运行在 Jvm 上面,那么考虑使用 Moshi(Moshi的基本使用)

你可能感兴趣的:(Kotlin)