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

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

相关推荐
麦兜*1 小时前
Spring Boot 集成 Docker 构建与发版完整指南
java·spring boot·后端·spring·docker·系统架构·springcloud
Cisyam^1 小时前
Go环境搭建实战:告别Java环境配置的复杂
java·开发语言·golang
CHENFU_JAVA1 小时前
使用EasyExcel实现Excel单元格保护:自由锁定表头和数据行
java·excel
青云交2 小时前
Java 大视界 -- 基于 Java 的大数据实时流处理在智能电网分布式电源接入与电力系统稳定性维护中的应用(404)
java·大数据·分布式·智能电网·flink 实时流处理·kafka 数据采集·iec 61850 协议
xzkyd outpaper2 小时前
Android中APK包含哪些内容?
android
蹦极的考拉2 小时前
网站日志里面老是出现{pboot:if((\x22file_put_co\x22.\x22ntents\x22)(\x22temp.php\x22.....
android·开发语言·php
仰望星空@脚踏实地3 小时前
maven scope 详解
java·maven·scope
M_Reus_113 小时前
Groovy集合常用简洁语法
java·开发语言·windows
带刺的坐椅4 小时前
10分钟带你体验 Solon 的状态机
java·solon·状态机·statemachine
小鹅叻4 小时前
MyBatis题
java·tomcat·mybatis