在这里插入图片描述

摘要

本文属于 KMP 三方库鸿蒙化适配合集,聚焦 Kotlin 官方序列化库 kotlinx.serialization 在 OpenHarmony 上的适配实践。文章提出「语义层 + 引擎层 + 验收页」的三层架构:语义层用 JsonElement 树与 KSerializer<T> 契约保留原库的纯映射,引擎层复用 ArkTS 自带的 JSON 设施完成最终编解码,验收页在真机上验证嵌套对象的序列化与反序列化。全文只讲本仓库真实落地的代码,并总结了 JSON.parse 类型摩擦、严格模式禁参数属性、手写解析器转义处理等踩坑经验。

目录

一、为什么选它

kotlinx.serialization 是 Kotlin 官方的跨平台序列化库,把“类型化对象 <-> JSON”拆成两层:类型化的 Serializer<T>(描述怎么把 T 编成 JsonElement、怎么解回 T),以及平台无关的 JsonElement 树(JsonPrimitive / JsonObject / JsonArray)。在 KMP 项目里它几乎是“标配”——网络响应、本地缓存、配置落盘都离不了。

到了 OpenHarmony,系统没有 Kotlin 编译器在编译期为 @Serializable 生成 Serializer 的能力,但 ArkTS 运行时自带 ECMAScript 的 JSON 全局对象。所以适配思路是:保留原库“对象 <-> JsonElement 树”的纯映射(语义层),把“JsonElement 树 <-> 字符串”的最终编解码交给系统 JSON 设施(引擎层)。这同样是“真接口真实现”,而不是糊一个假壳。

二、适配总思路:三层架构

  1. 语义层(不碰 @kit.*):定义 JsonElement 树、KSerializer<T> 契约,以及手写 parseJson 解析器(纯算法)。
  2. 引擎层(桥系统 JSON 设施):OhosSerializationEngine 薄封装系统 JSON,encode/decode 委托给语义层门面。
  3. 验收页: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 真实生效。

运行效果如下:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

七、踩坑小结

  1. JSON.parse 的类型摩擦:严格模式下返回 Object 不能动态索引,改用自写 parseJson 产出强类型 JsonElement 树。
  2. 严格模式禁参数属性:constructor(public x) 非法,所有字段用普通参数 + this.x = x。
  3. 手写解析器要处理转义:\"、\\、\n、\uXXXX 等转义必须覆盖,否则中文/特殊字符会解错。
  4. 嵌套靠组合:嵌套对象的 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

Logo

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

更多推荐