Kotlinx序列化多平台兼容性详解

kotlinx.serialization 是 Kotlin 官方的多平台序列化库,设计时充分考虑了 Kotlin Multiplatform(KMP)的兼容性。以下是其多平台兼容性的关键特性和注意事项:


1. 核心多平台支持

  • 跨平台序列化逻辑 :在 commonMain 中定义可序列化的数据类和序列化/反序列化逻辑,可在所有目标平台(JVM、JS、Native)共享。
  • 统一注解@Serializable@SerialName 等注解在公共代码中直接使用。
  • 格式支持kotlinx-serialization-jsonkotlinx-serialization-cbor 等核心格式均支持多平台。

2. 平台特定实现

不同平台的序列化行为由库自动处理,但需注意:

  • JVM :最稳定,支持反射(如 PolymorphicSerializer),但推荐显式注册序列化模块以避免性能问题。
  • Kotlin/JS :行为与 JVM 基本一致,但需注意:
    • 日期格式:JS 的 Date 与 Java 不同,建议统一使用 kotlinx-datetime 处理日期。
  • Kotlin/Native
    • 无反射 :Native 平台禁用反射,必须显式注册多态子类(如 Json { serializersModule = myModule })。
    • 并发限制 :序列化器初始化需在单线程(如 @SharedImmutable)完成。
    • 资源访问:读取文件需使用平台特定代码(如 iOS 的 NSBundle)。

3. 多平台配置最佳实践

共享数据类

kotlin 复制代码
// commonMain/kotlin
import kotlinx.serialization.Serializable

@Serializable
data class Project(val id: Int, val name: String, val isPublic: Boolean)

序列化模块注册(Native 关键!)

kotlin 复制代码
// commonMain/kotlin
import kotlinx.serialization.modules.*

val myModule = SerializersModule {
    polymorphic(Project::class) {
        subclass(PrivateProject::class) // 显式注册多态子类
    }
}

// 在 Native 等平台使用模块
val json = Json { serializersModule = myModule }

平台差异处理(expect/actual)

kotlin 复制代码
// commonMain/kotlin
expect fun readConfigFile(): String

// androidMain/kotlin
actual fun readConfigFile() = File("config.json").readText()

// iosMain/kotlin
actual fun readConfigFile(): String {
    val path = NSBundle.mainBundle.pathForResource("config", "json") 
    return NSString(contentsOfFile = path!!, encoding = NSUTF8StringEncoding) as String
}

4. 常见问题与解决

问题 1:Native 平台反序列化失败

  • 原因:未注册多态子类或使用了反射。

  • 解决 :显式注册所有子类:

    kotlin 复制代码
    Json {
        serializersModule = SerializersModule {
            polymorphic(Shape::class) {
                subclass(Circle::class)
                subclass(Rectangle::class)
            }
        }
    }

问题 2:日期格式不一致

  • 解决 :统一使用 Instant(推荐 kotlinx-datetime):

    kotlin 复制代码
    @Serializable
    data class Event(
        @Serializable(with = InstantSerializer::class)
        val time: Instant
    )

问题 3:JS 平台 Long 类型溢出

  • 解决 :在 JSON 配置中使用字符串表示 Long:

    kotlin 复制代码
    Json { explicitNulls = false; useAlternativeNames = true }

5. 构建配置要点

build.gradle.kts 中确保:

kotlin 复制代码
kotlin {
    jvm()
    js(IR) { browser() }
    iosX64()

    sourceSets {
        commonMain {
            dependencies {
                implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.0")
            }
        }
    }
}

总结

  • 优势kotlinx.serialization 在 KMP 中实现了高度代码共享,核心逻辑可完全写在 commonMain
  • 注意
    • Native 平台:禁用反射,必须显式注册多态类型。
    • 日期/长整型 :使用跨平台库(如 kotlinx-datetime)或统一配置。
    • 资源访问 :通过 expect/actual 实现平台差异化。
  • 推荐:始终使用最新版本(如 1.6.0+)以获得最佳多平台支持。

通过遵循显式注册、避免反射和统一数据表示,可高效实现全平台一致的序列化逻辑。

相关推荐
程序员JerrySUN3 分钟前
RK3588 Android SDK 实战全解析 —— 架构、原理与开发关键点
android·架构
老虎06274 分钟前
数据结构(Java)--位运算
java·开发语言·数据结构
yanjiaweiya5 分钟前
云原生-集群管理续
java·开发语言·云原生
写不出来就跑路11 分钟前
暑期实习感悟与经验分享:从校园到职场的成长之路
java·开发语言·经验分享·spring boot
泰勒疯狂展开15 分钟前
Java研学-MongoDB(二)
java·mongodb
移动开发者1号15 分钟前
Java Phaser:分阶段任务控制的终极武器
android·kotlin
程序员张34 小时前
Maven编译和打包插件
java·spring boot·maven
ybq195133454315 小时前
Redis-主从复制-分布式系统
java·数据库·redis
weixin_472339466 小时前
高效处理大体积Excel文件的Java技术方案解析
java·开发语言·excel
小毛驴8506 小时前
Linux 后台启动java jar 程序 nohup java -jar
java·linux·jar