资讯详情

cangjie_stdx 中的 ToJson 接口:JsonValue 与 DataModel 双向转换实战指南

📅 2026/10/15 19:03:57 | 华诺云谱 👁 阅读
cangjie_stdx 中的 ToJson 接口:JsonValue 与 DataModel 双向转换实战指南
标准库网络密码学并发编程【免费下载链接】cangjie_stdx仓颉编程语言提供了 stdx 模块该模块提供了网络、安全等领域的通用能力。项目地址https://gitcode.com/Cangjie/cangjie_stdx点击查看免费下载导读本文围绕 cangjie_stdx 中stdx.encoding.json包的ToJson接口展开深入解析其如何打通 JSON 数据JsonValue与中间数据模型DataModel之间的双向转换。读者将掌握ToJson接口的定义、DataModel扩展实现的底层映射逻辑并学会借助 serialization 包完成自定义类型 ⇄ JSON 字符串的完整序列化闭环。1. ToJson 接口概览在stdx.encoding.json包中ToJson接口承担着桥梁角色它定义了 JsonValue 与 DataModel 之间的双向转换协议。该接口声明位于源码 src/stdx/encoding/json/to_json.cj完整签名如下public interface ToJson { static func fromJson(jv: JsonValue): DataModel func toJson(): JsonValue }接口包含两个成员职责恰好相反成员签名方向功能fromJson(jv)static func fromJson(jv: JsonValue): DataModelJSON → 数据模型将 JsonValue 转换为 DataModel 对象toJson()func toJson(): JsonValue数据模型 → JSON将自身转换为 JsonValue在 json 包总览文档 的 API 列表中ToJson是全包唯一的接口类型被明确标注为用于实现 JsonValue 和 DataModel 的相互转换。理解这两个概念是掌握该接口的前提JsonValuestdx.encoding.json包对 JSON 数据格式的封装覆盖 object、array、string、number、true、false、null 七种形态其抽象基类与JsonKind枚举定义于 src/stdx/encoding/json/json_value.cj具体实现类包括JsonObject、JsonArray、JsonString、JsonInt、JsonFloat、JsonBool、JsonNull。DataModelstdx.serialization.serialization包中的抽象中间数据层定义于 src/stdx/serialization/serialization/data_model.cj其子类DataModelNull、DataModelBool、DataModelInt、DataModelFloat、DataModelString、DataModelSeq、DataModelStruct分别对应标量、序列与结构体三类数据形态与SerializableT接口serializable.cj配合构成自定义类型 → DataModel的通用序列化模型。2. 接口成员详解2.1 static func fromJson(JsonValue)static func fromJson(jv: JsonValue): DataModel参数jv—— 待转换的 JsonValue 实例。返回值转换得到的 DataModel 对象。语义作为静态方法它接收一个已解析完成的 JsonValue典型来源是JsonValue.fromStr(s)见 json_value.cj将其整体降级为与序列化框架统一的 DataModel 表示。2.2 func toJson()func toJson(): JsonValue返回值转换得到的 JsonValue。异常转换失败时抛出 JsonException该类定义于 src/stdx/encoding/json/json_exception.cj带可选的message参数。语义作为实例方法它把当前 DataModel 对象包装成对应的 JsonValue供后续toString()/toJsonString()等输出方法消费。3. DataModel 的 ToJson 扩展实现接口本身只有声明真正可用的转换逻辑来自extend DataModel : ToJson扩展。该扩展同样位于 src/stdx/encoding/json/to_json.cj声明形式为extend DataModel : ToJson其父类型为 ToJson 接口本身。通过扩展所有 DataModel 及其子类实例无需修改 serialization 包即可直接获得 JSON 双向转换能力——这正是以 json 包为桥梁、以扩展机制为手段的模块解耦设计。3.1 扩展实现fromJson 的映射规则public static func fromJson(jv: JsonValue): DataModel的核心是match模式匹配把七种 JsonValue 形态逐一映射到 DataModel 子类public static func fromJson(jv: JsonValue): DataModel { match (jv) { case jb: JsonBool DataModelBool(jb.getValue()) case ji: JsonInt DataModelInt(ji.getValue()) case jf: JsonFloat DataModelFloat(jf.getValue()) case js: JsonString DataModelString(js.getValue()) case ja: JsonArray buildDMSeq(ja) case jo: JsonObject buildDMStruct(jo) case _ DataModelNull() } }对应的完整映射表依据 to_json.cj 源码JsonValue 形态映射结果说明JsonBoolDataModelBool布尔值直通JsonIntDataModelInt64 位整数直通JsonFloatDataModelFloat浮点数直通JsonStringDataModelString字符串直通JsonArrayDataModelSeq走buildDMSeq(ja)递归JsonObjectDataModelStruct走buildDMStruct(jo)递归其他含JsonNullDataModelNull兜底为 null递归处理容器是fromJson的关键设计buildDMSeq(ja)to_json.cj创建DataModelSeq遍历JsonArray的每一项元素并递归调用fromJson将结果加入序列转换前先list.reserve(ji.size)预分配容量避免列表扩容开销。buildDMStruct(jo)to_json.cj创建DataModelStruct遍历JsonObject的键值对每个键值递归转换为Field(str, dm)后加入字段列表若遇到无法匹配的 JsonValue 类型则抛出JsonException(Internal error: unmatched JsonValue type.)。从源码结构可以看出fromJson对嵌套 JSON数组套对象、对象套数组具备天然的支持能力这与 json_value_sample.md 中展示的深层嵌套 JSON 解析场景相印证。3.2 扩展实现toJson 的映射规则public func toJson(): JsonValue是fromJson的逆操作同样基于matchpublic func toJson(): JsonValue { match (this) { case _: DataModelNull return JsonNull() case dmb: DataModelBool return JsonBool(dmb.getValue()) case dmi: DataModelInt return JsonInt(dmi.getValue()) case dmf: DataModelFloat return JsonFloat(dmf.getValue()) case dmstr: DataModelString return JsonString(dmstr.getValue()) case dmseq: DataModelSeq return toJson(dmseq) case dms: DataModelStruct return toJson(dms) case _ throw JsonException(Internal error: unmatched DataModel type.) } }映射表依据 to_json.cj 源码DataModel 形态映射结果说明DataModelNullJsonNull()空值DataModelBoolJsonBool(...)布尔值直通DataModelIntJsonInt(...)整数直通DataModelFloatJsonFloat(...)浮点数直通DataModelStringJsonString(...)字符串直通DataModelSeqJsonArray走私有toJson(dmseq)DataModelStructJsonObject走私有toJson(dms)其他抛JsonException兜底报错容器方向的逆递归同样成对存在toJson(dmseq)to_json.cj遍历DataModelSeq的 items逐个调用元素自身的toJson()后add进JsonArray。toJson(dms)to_json.cj遍历DataModelStruct的字段列表将Field的键名与递归转换后的值通过jo.put(fie.getName(), value)写入JsonObject。需要特别注意的是DataModelStruct.toJson()对字段值的处理字段值本身就是DataModel直接调用fie.getData().toJson()即可因此任意深度的嵌套结构体都能被完整还原为 JSON。4. 实战自定义类型与 JSON 字符串的完整转换闭环仅看接口本身不足以体现价值将ToJson与 serialization 包的SerializableT接口串联才能实现真正的业务闭环。完整示例来自 json_samples/to_json_sample.md其工作流可概括为JSON 字符串 → JsonValue.fromStr → JsonValue → DataModel.fromJson → DataModel → Person.deserialize → 自定义类型实例 → person.serialize → DataModel → DataModel.toJson → JsonValue → toJsonString → JSON 字符串4.1 定义实现 Serializable 的自定义类型首先为业务类实现SerializableT接口该接口定义于 serializable.cj要求实现serialize(): DataModel与static deserialize(dm: DataModel): Timport stdx.serialization.serialization.* import stdx.encoding.json.* // 定义 Location 类实现 Serializable 接口 class Location : SerializableLocation { var country: String var province: String public func serialize(): DataModel { return DataModelStruct().add(fieldString(country, country)).add(fieldString(province, province)) } public static func deserialize(dm: DataModel): Location { let dms match (dm) { case data: DataModelStruct data case _ throw Exception(this data is not DataModelStruct) } let result Location() result.country String.deserialize(dms.get(country)) result.province String.deserialize(dms.get(province)) return result } } // 定义 Person 类实现 Serializable 接口含嵌套 Location 字段 class Person : SerializablePerson { var name: String var age: Int64 0 var loc: OptionLocation OptionLocation.None public func serialize(): DataModel { return DataModelStruct() .add(fieldString(name, name)) .add(fieldInt64(age, age)) .add(fieldOptionLocation(loc, loc)) } public static func deserialize(dm: DataModel): Person { let dms match (dm) { case data: DataModelStruct data case _ throw Exception(this data is not DataModelStruct) } let result Person() result.name String.deserialize(dms.get(name)) result.age Int64.deserialize(dms.get(age)) result.loc OptionLocation.deserialize(dms.get(loc)) return result } }可以看到serialize()借助fieldK(键名, 值)构造字段deserialize()则用dms.get(键名)取值并调用对应类型的deserialize还原。OptionLocation这类容器类型同样具备Serializable扩展见 serializable.cj因此嵌套与可空字段都能被正确处理。4.2 反序列化JSON 字符串 → 自定义类型main() { // 准备 JSON 字符串 let jsonString ##{ name: A, age: 30, loc: { country: China, province: Beijing } }## // 从 JSON 字符串转换为自定义类型反序列化 let jsonValue JsonValue.fromStr(jsonString) // String → JsonValue let dataModel DataModel.fromJson(jsonValue) // JsonValue → DataModelToJson 静态方法 let person Person.deserialize(dataModel) // DataModel → PersonSerializable 静态方法 println(反序列化结果:) println(姓名: ${person.name}) println(年龄: ${person.age}) println(国家: ${person.loc.getOrThrow().country}) println(省份: ${person.loc.getOrThrow().province}) }三段转换各自职责清晰JsonValue.fromStr负责语法解析DataModel.fromJson即 ToJson 扩展负责语义降级Person.deserialize负责业务还原。运行输出反序列化结果: 姓名: A 年龄: 30 国家: China 省份: Beijing4.3 序列化自定义类型 → JSON 字符串// 从自定义类型转换为 JSON 字符串序列化 println(\n序列化结果:) let serializedDataModel person.serialize() // Person → DataModelSerializable let jsonObject serializedDataModel.toJson().asObject() // DataModel → JsonValueToJson 实例方法 println(jsonObject.toJsonString()) // JsonValue → 格式化 JSON 字符串这里serializedDataModel.toJson()调用的正是 ToJson 扩展的实例方法asObject()是 JsonValue 的类型断言方法将结果收窄为JsonObject以便调用toJsonString()。运行输出为带缩进的格式化 JSON序列化结果: { name: A, age: 30, loc: { country: China, province: Beijing } }5. ToJson 在仓库其他模块中的应用ToJson并非孤立设计仓库内已有真实调用方可作为功能正确性的佐证unittest 数据策略src/stdx/unittest/data/json_strategy.cjJsonStrategyT读取 JSON 文件后先用JsonValue.fromStr解析再通过DataModel.fromJson(data) as DataModelSeq转为数据模型供SerializableProvider做参数化测试——这是fromJson在测试框架中的实际落地。json_stream 流式读写src/stdx/encoding/json/stream/json_deserializable.cj 与 json_reader.cj流式 API 中JsonDeserializableT的T.fromJson(r)、ArrayListT.fromJson(r)等实现体现了类型 → JSON转换思想在流式场景下的延伸以JsonReader/JsonWriter替代JsonValue。6. 小结与最佳实践职责定位ToJson只管JsonValue ⇄ DataModel的中间层转换String ⇄ JsonValue由JsonValue.fromStr/toJsonString负责DataModel ⇄ 自定义类型由SerializableT负责。三段式管线各司其职可通过 json 包总览 与 serialization 包文档 对照理解。完整链路自定义类型反序列化用JsonValue.fromStr→DataModel.fromJson→T.deserialize序列化用t.serialize→DataModel.toJson→toJsonString。嵌套结构数组、对象、Option等在两层递归转换下均可无损往返。异常处理toJson/fromJson在遇到不可转换的类型时抛出 JsonException业务代码建议对转换失败路径做try-catch兜底。扩展机制extend DataModel : ToJson展示了仓颉扩展特性在跨包能力注入上的价值——不侵入 serialization 包即可让既有数据模型获得 JSON 能力这也为二次开发中给第三方类型补充序列化能力提供了可复用的范式。赞分享标准库网络密码学并发编程【免费下载链接】cangjie_stdx仓颉编程语言提供了 stdx 模块该模块提供了网络、安全等领域的通用能力。项目地址https://gitcode.com/Cangjie/cangjie_stdx点击查看免费下载相关推荐仓颉 stdx.encoding.json 的 ToJson 接口详解JsonValue 与 DataModel 双向转换指南仓颉 stdx.encoding.json 的 ToJson 接口详解JsonValue 与 DataModel 双向转换指南 本文围绕仓颉标准库扩展can标准库网络密码学并发编程仓颉 stdx.encoding.json 的 ToJson 接口实现 JsonValue 与 DataModel 双向转换的完整指南仓颉 stdx.encoding.json 的 ToJson 接口实现 JsonValue 与 DataModel 双向转换的完整指南 ToJson 是仓颉编文档知识库教程OpenHarmony仓颉 cangjie_stdx 实战JsonValue 与 String 双向转换完全指南仓颉 cangjie_stdx 实战JsonValue 与 String 双向转换完全指南 stdx.encoding.json 是仓颉标准库扩展cangj标准库网络密码学并发编程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑