Kotlin Multiplatform 三方库 kotlinx-serialization-json 的 OpenHarmony 鸿蒙化适配实战(Kotlin/Native 编译 .so + NAPI 桥接 ArkTS)

库版本:kotlinx-serialization-json 1.9.1-OHOS-003(鸿蒙切片)|验证环境:Kotlin Multiplatform 2.2.21(Kotlin 2.2.21-1.0.0 定制版)|DevEco Studio 26.0.0|DevEco 模拟器|HarmonyOS 7.0.0(API 26)

在跨平台开发里,kotlinx-serialization-json 是 Kotlin 生态事实标准的序列化库。但要在鸿蒙上用它,绝不是"引个包"就行——鸿蒙的 Kotlin 支持走 Kotlin/Native 路线,需要把序列化逻辑编译成动态库 .so,再通过 NAPI 暴露给 ArkTS(UI 层)。本文记录我把 kotlinx-serialization-json 完整跑上鸿蒙的全过程:从选对鸿蒙切片版本、Kotlin/Native 编译双 ABI 的 .so、NAPI 桥接,到修掉一个让 ArkTS JSON.parse 崩溃的隐蔽 bug,最终在 DevEco 模拟器上 10/10 全绿通过验收。

验收效果预览 *先睹为快:DevEco 模拟器实测,10 个序列化用例全部 PASS,输出为真实序列化结果* ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/d14e925c9f8a40d784d93e2406e79467.png)

一、适配目标与整体链路

目标很朴素:在鸿蒙模拟器里跑一个 ArkTS 应用,点一下按钮,真实调用 Kotlin/Native 里的序列化逻辑,把结果返回并渲染出来——以此证明整条链路真正打通,而不是 UI 上摆几个写死的字符串。

整体链路:

在这里插入图片描述

二、工程结构

kmp-serialization-demo/
├── serialization-core/        # 库模块:kotlinx-serialization-json 封装
│   └── src/commonMain/kotlin/ # 公共 API(100% 复用上游)
├── example/
│   ├── shared/                # 共享验收逻辑(10 个用例)
│   │   └── src/commonMain/kotlin/SerializationChecks.kt
│   ├── nativeApp/             # Kotlin/Native 桥接层 → libohosserialization.so
│   │   └── src/ohosMain/kotlin/NativeBridge.kt   # @CName 导出 JSON
│   └── ohosApp/               # ArkTS 鸿蒙应用
│       └── entry/src/main/ets/pages/Index.ets
└── settings.gradle.kts / build.gradle.kts / gradle.properties
  • serialization-core:封装序列化能力,公共 API 完全复用上游;
  • example/shared:定义 10 个验收用例——基本类型、嵌套对象、集合、默认值填充、sealed 多态、忽略未知键等;
  • example/nativeApp:把 shared 编译成 libohosserialization.so,@CName 导出;
  • example/ohosApp:ArkTS UI,通过 NAPI 调用 .so。

三、适配过程:四个关键步骤

验收效果预览 ### 3.1 选对序列化库的鸿蒙切片版本

这是第一个、也是最隐蔽的坑。项目最初写的是 kotlinx-serialization-json:1.9.0-ohos.1,但这个版本在中央仓库和定制仓库里都不存在,Gradle 依赖解析直接失败。

我列出定制 Nexus 仓库里 kotlinx-serialization-json 的全部版本,发现可用的鸿蒙切片是 1.9.1-OHOS-003,并通过 HTTP HEAD 请求确认它确实带 ohosArm64 / ohosX64 的 klib:

kotlinx-serialization-json-ohosArm64-1.9.1-OHOS-003.klib   ✅
kotlinx-serialization-json-ohosx64-1.9.1-OHOS-003.klib     ✅

把版本改为 1.9.1-OHOS-003 后,依赖解析通过。

经验:鸿蒙生态的 KMP 库版本号往往是 x.y.z-OHOS-NNN 这种定制切片,不能想当然写 upstream 版本号。先查仓库里真实存在什么,再写进 build.gradle.kts。

3.2 用 Kotlin/Native 编译出双 ABI 的 .so

鸿蒙的 Kotlin/Native target 是 ohosArm64(真机)和 ohosX64(模拟器)。用 JDK 21 作为 JAVA_HOME 执行:

$env:JAVA_HOME = "C:/Users/nwu/Desktop/z_pig/jdk-21.0.2"
.\gradlew.bat :example:nativeApp:linkReleaseSharedOhosArm64 `
              :example:nativeApp:linkReleaseSharedOhosX64

产物:

example/nativeApp/build/bin/ohosArm64/releaseShared/libohosserialization.so
example/nativeApp/build/bin/ohosX64/releaseShared/libohosserialization.so

把两个 ABI 的 .so 分别拷到 ArkTS 工程的 entry/libs/arm64-v8a/ 和 entry/libs/x86_64/。

3.3 NAPI 桥接:从 ArkTS 调进 Kotlin/Native

Kotlin 侧用 @CName 把结果以 JSON 字符串导出:

@CName("runChecks")
fun runChecks(): String = buildJsonResult(runAllChecks())

ArkTS 侧引入 NAPI 薄层并调用:

import serializationNative from 'libserialization.so';

const jsonStr: string = serializationNative.runChecks();
const parsed = JSON.parse(jsonStr) as CheckResult;
this.result = parsed;

UI 触发入口如下——深色现代化界面:渐变背景 + 氛围光斑、顶部胶囊标签(KMP 2.2.21 / HarmonyOS 7.0.0 / API 26)、发光运行按钮、空状态 { } 占位。

初始空状态 *初始页:深蓝渐变 + 胶囊标签 + 发光按钮,点击「运行全部验收用例」触发 NAPI 调用*

3.4 修复一个让 JSON.parse 崩溃的 bug

链路打通后,UI 却报 Unexpected end Text in JSON。排查发现根因不在 NAPI,而在 Kotlin 侧 buildJsonResult()——它手工拼 JSON 字符串时只转义了引号,没转义换行符。而用例里 Json { prettyPrint = true } 会让 output 字段带大量真实换行,导致整个返回串不是合法 JSON,ArkTS 一解析就崩。

修复方式是加一个完整的转义函数:

private fun jsonEscape(s: String): String = buildString(s.length) {
    for (c in s) {
        when (c) {
            '"' -> append("\\\"")
            '\\' -> append("\\\\")
            '\n' -> append("\\n")
            '\r' -> append("\\r")
            '\t' -> append("\\t")
            else -> append(c)
        }
    }
}

经验:跨语言传 JSON,永远不要手工拼字符串。如果必须拼,转义要完整(引号、反斜杠、换行、回车、制表符)。更稳妥的做法是直接用 kotlinx-serialization 自己序列化结果对象。

四、运行效果(DevEco 模拟器实测)

明细列表每条用例一张磨砂玻璃卡:状态圆点 + PASS 徽标 + 等宽字体代码块展示真实序列化输出。下面三段分别对应不同类型用例的实测结果。

基本类型与嵌套对象——输出是真实 JSON(如 {"id": 1, "name": "张三"}):

基本类型用例 *基本数据类序列化、嵌套对象,全部 PASS*

sealed 多态——成功(绿点)与失败(红点)用例的红绿对比清晰可见:

sealed 多态用例 *sealed class 多态序列化/反序列化,类型判别字段正确还原*

Map 与默认值填充——含 extensionProperties 等复杂结构:

Map 用例 *Map 序列化、忽略未知键、默认值填充等全部 PASS*

应用已正常安装到 DevEco 模拟器并可拉起:

桌面入口 *DevEco 模拟器桌面,应用入口图标正常显示*

10 个用例全部 PASS,覆盖:基本类型序列化、嵌套对象、集合、Map、默认值填充、sealed 多态、忽略未知键等,输出均为真实序列化结果而非 mock。

五、FAQ

Q1:Gradle 依赖解析失败,提示找不到 1.9.0-ohos.1?这个版本不存在。查鸿蒙定制仓库(maven.eazytec-cloud.com)里真实存在的 OHOS 切片版本,本文用 1.9.1-OHOS-003。

Q2:Kotlin/Native 编译报 JDK 相关错误?用 JDK 21 作为 JAVA_HOME(DevEco 自带 JBR 或 Temurin 均可)。

Q3:命令行 hvigor 构建报 Invalid value of 'DEVECO_SDK_HOME'?先 export DEVECO_SDK_HOME=<DevEco 安装目录>/sdk,再 hvigorw --stop-daemon 后重试。

Q4:往 hvigor-config.json5 的 dependencies 里写了说明文字,pnpm install 失败?该字段只放真实 npm 包,别写 libohosserialization.so (arm64-v8a) 这类描述,否则 pnpm 会当依赖解析报错。

Q5:ArkTS JSON.parse 报 Unexpected end Text in JSON?多半是 Kotlin 侧手工拼 JSON 没转义换行/引号。补全 jsonEscape,或直接用序列化库生成结果字符串。

Q6:hdc 自动化点击按钮没反应?别凭截图比例估算坐标,用 hdc shell uitest dumpLayout 查控件真实 bounds,再按中心点 uitest uiInput click x y。

六、总结与参考

把 kotlinx-serialization-json 跑上鸿蒙,本质是打通 KMP → Kotlin/Native(ohos target) → .so → NAPI → ArkTS 这条链。关键不在某一步多难,而在于每一步都有"看起来对但其实不对"的细节:版本切片、JDK、DEVECO_SDK_HOME、JSON 转义、点击坐标。这次 10/10 全绿,证明整条链路真实可用。
OpenHarmony 三方库社区地址:https://atomgit.com/oh-tpc
github 三方库地址:https://github.com/Kotlin/kotlinx.serialization
官方文档地址:https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/serialization-guide.md
鸿蒙定制仓库地址:https://maven.eazytec-cloud.com/nexus/repository/maven-public/
鸿蒙适配版:https://atomgit.com/oh-tpc/serialization-core

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐