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

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

相关推荐
维齐洛波奇特利(male)19 分钟前
@Pointcut(“execution(* com.hdzx..*(..))“)切入点与aop 导致无限循环
java·开发语言
色空大师20 分钟前
【日志文件配置详解】
java·logback·log4j2·日志
IT枫斗者23 分钟前
构建具有执行功能的 AI Agent:基于工作记忆的任务规划与元认知监控架构
android·前端·vue.js·spring boot·后端·架构
迷藏49429 分钟前
**发散创新:基于角色与属性的混合权限模型在微服务架构中的实战落地**在现代分布式系统中,
java·python·微服务·云原生·架构
码以致用38 分钟前
Java垃圾回收器笔记
java·jvm·笔记
暴力袋鼠哥39 分钟前
基于springboot与vue的ai多模态数据展示看板
java·spring boot
用户693717500138444 分钟前
XChat 为什么选择 Rust 语言开发
android·前端·ios
用户8307196840821 小时前
VS Code Java开发配置与使用经验分享
java·visual studio code
林栩link1 小时前
【车载 Android】实践跨进程 UI 融合渲染
android