Kotlin Multiplatform for OpenHarmony 实战:kotlinx-serialization JSON 适配

摘要
本文属于 KMP 三方库鸿蒙化适配合集,聚焦 Kotlin 官方序列化库 kotlinx.serialization 在 OpenHarmony 上的适配实践。文章提出「语义层 + 引擎层 + 验收页」的三层架构:语义层用 JsonElement 树与 KSerializer<T> 契约保留原库的纯映射,引擎层复用 ArkTS 自带的 JSON 设施完成最终编解码,验收页在真机上验证嵌套对象的序列化与反序列化。全文只讲本仓库真实落地的代码,并总结了 JSON.parse 类型摩擦、严格模式禁参数属性、手写解析器转义处理等踩坑经验。
目录
- 一、为什么选它
- 二、适配总思路:三层架构
- 三、语义层:JsonElement 树 + Serializer 契约
- 四、为什么手写 JSON 解析器
- 五、引擎层:桥系统 JSON 设施
- 六、验收页:真机上验证
- 七、踩坑小结
- 社区引导
一、为什么选它
kotlinx.serialization 是 Kotlin 官方的跨平台序列化库,把“类型化对象 <-> JSON”拆成两层:类型化的 Serializer<T>(描述怎么把 T 编成 JsonElement、怎么解回 T),以及平台无关的 JsonElement 树(JsonPrimitive / JsonObject / JsonArray)。在 KMP 项目里它几乎是“标配”——网络响应、本地缓存、配置落盘都离不了。
到了 OpenHarmony,系统没有 Kotlin 编译器在编译期为 @Serializable 生成 Serializer 的能力,但 ArkTS 运行时自带 ECMAScript 的 JSON 全局对象。所以适配思路是:保留原库“对象 <-> JsonElement 树”的纯映射(语义层),把“JsonElement 树 <-> 字符串”的最终编解码交给系统 JSON 设施(引擎层)。这同样是“真接口真实现”,而不是糊一个假壳。
二、适配总思路:三层架构
- 语义层(不碰
@kit.*):定义JsonElement树、KSerializer<T>契约,以及手写parseJson解析器(纯算法)。 - 引擎层(桥系统 JSON 设施):
OhosSerializationEngine薄封装系统JSON,encode/decode委托给语义层门面。 - 验收页:
SerializationDemo在真机/模拟器上把User、嵌套Profile编码成 JSON 再反解回来。
三、语义层:JsonElement 树 + Serializer 契约
Serialization.ets 只承载数据结构与纯算法,没有任何平台依赖(注意 ArkTS 严格模式禁止构造参数属性,字段显式赋值):
export interface KSerializer<T> {
readonly descriptor: SerialDescriptor;
serialize(value: T): JsonElement;
deserialize(element: JsonElement): T;
}
export class Json {
encodeToString<T>(value: T, serializer: KSerializer<T>): string {
return JSON.stringify(serializer.serialize(value).toPlain());
}
decodeFromString<T>(text: string, serializer: KSerializer<T>): T {
return serializer.deserialize(parseJson(text));
}
}
这与 kotlinx.serialization 的“KSerializer<T> + Json 门面”语义一致——你为每个数据类手写一份 Serializer,剩下的交给门面。
四、为什么手写 JSON 解析器
ArkTS 严格模式下 JSON.parse 返回 Object 类型,之后无法安全做动态属性索引(obj['key'] 会被拦),而 JSON.stringify 对纯数据则完全可用。因此:
- 编码:用系统
JSON.stringify(安全、零依赖)。 - 解码:放一个手写递归下降
parseJson,把字符串解析成我们自己的JsonElement树,再交给deserialize。
手写解析器其实更贴近原库——kotlinx 的 JSON 解析同样是自实现的,而不是简单调平台 API。
五、引擎层:桥系统 JSON 设施
OhosSerializationEngine.ets 只做一件事:把“平台相关”的编解码交给系统,自己不造轮子。
import { Json, KSerializer } from './Serialization';
export class OhosSerializationEngine {
private readonly json: Json = new Json();
encode<T>(value: T, serializer: KSerializer<T>): string {
return this.json.encodeToString(value, serializer); // 内部 JSON.stringify
}
decode<T>(text: string, serializer: KSerializer<T>): T {
return this.json.decodeFromString(text, serializer); // 内部手写 parseJson
}
}
要点:我们没有引入任何第三方 JSON 库,而是复用鸿蒙/ArkTS 已经稳定提供的 JSON 能力——这正是“真接口真实现”的体现。
六、验收页:真机上验证
我的开发界面如下:

SerializationDemo.ets 定义了 User、Address、Profile(含 User + Address + tags[] 嵌套)以及对应的手写 Serializer。四个按钮:序列化 User、反序列化 User、序列化嵌套 Profile、反序列化 Profile。
运行时能看到:点“序列化 User”输出 {"name":"张三","age":28,"email":"...","active":true};点“反序列化 Profile”能正确还原出 user.name、address.city、tags 数组——证明 JSON 序列化 API 真实生效。
运行效果如下:





七、踩坑小结
JSON.parse的类型摩擦:严格模式下返回Object不能动态索引,改用自写parseJson产出强类型JsonElement树。- 严格模式禁参数属性:
constructor(public x)非法,所有字段用普通参数 +this.x = x。 - 手写解析器要处理转义:
\"、\\、\n、\uXXXX等转义必须覆盖,否则中文/特殊字符会解错。 - 嵌套靠组合:嵌套对象的
Serializer直接复用子Serializer(o.put('user', userSerializer.serialize(...))),与原库组合式写法一致。
社区引导
欢迎加入 KMP&CMP 鸿蒙社区:https://atomgit.com/CPF-KMP-CMP
本适配全部源码已开源在 AtomGit:https://atomgit.com/wdracky/kmp-ohos-adapters/tree/main/kotlinx-serialization
如果你在适配过程中用到了 AI 辅助工具,推荐码道(AtomCode)专属通道
https://developer.huaweicloud.com/codeartsco.html?source=dmzntgwatomgit1&sourcead=dmzntgwatomgiths
更多推荐



所有评论(0)