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+)以获得最佳多平台支持。

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

相关推荐
rengang662 分钟前
105-Spring AI Alibaba Module RAG 使用示例
java·人工智能·spring·rag·spring ai·ai应用编程
JIngJaneIL2 分钟前
机器人信息|基于Springboot的机器人门户展示系统设计与实现(源码+数据库+文档)
java·数据库·spring boot·机器人·论文·毕设·机器人门户展示系统
鬼火儿23 分钟前
15.<Spring Boot 日志>
java·后端
Mos_x24 分钟前
SpringBoot】Spring Boot 项目的打包配置
java·后端
qianbailiulimeng27 分钟前
【Spring Boot】Spring Boot解决循环依赖
java·后端
何中应28 分钟前
Spring Boot解决循环依赖的几种办法
java·spring boot·后端
donotshow28 分钟前
SpringBoot】Spring Boot 项目的打包配置
java·后端
鬼火儿30 分钟前
Spring Boot 整合 ShedLock 处理定时任务重复
java·后端
王元_SmallA31 分钟前
【Spring Boot】Spring Boot解决循环依赖
java·后端
小圆53140 分钟前
java-learn(9):常见算法,collection框架
java·开发语言·算法