Kotlin Multiplatform 三方库 kotlinx-serialization-json 的 OpenHarmony 鸿蒙化适配实战(Kotlin/Native 编译 .so + NAP
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,输出为真实序列化结果* 
一、适配目标与整体链路
目标很朴素:在鸿蒙模拟器里跑一个 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 class 多态序列化/反序列化,类型判别字段正确还原*
Map 与默认值填充——含 extensionProperties 等复杂结构:
*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
更多推荐


所有评论(0)