Files
serialization-cj/README.md
T

7.3 KiB
Raw Blame History

serializationsimcu::serialization

SimApi 全反射 JSON 序列化库(仓颉版),对齐 .NET System.Text.Json 的用法与注解风格。

  • 免标注:任意类(无参构造 + var 字段)无需实现接口、无需标注,开箱即用
  • 注解@SerializerPropertyName / @SerializerIgnore(对齐 [JsonPropertyName] / [JsonIgnore]
  • 继承支持@SerializerParent 宏解决父类字段序列化(Cangjie 反射限制)
  • API 对齐JsonSerializer.Serialize(obj, JsonOption) / Deserialize<T>(json, JsonOption)
  • 字段名_ 前缀与无下划线字段均支持(_name 原样输出 _namename 输出 name

快速开始

引入

两种方式任选其一:

方式一:中央仓(需先 cjpm publish 发布 simcu::serialization

[dependencies]
"simcu::serialization" = "1.0.3"

方式二:Git 仓库

[dependencies]
"simcu::serialization" = { git = "https://gitcode.com/simcu/serialization-cj.git", version = "1.0.3" }

本地开发也可用 path 依赖:"simcu::serialization" = { path = "../simapi-serialization" }

import simcu::serialization.*   // 一个 import 全量可用(注解 + 序列化器)

序列化 / 反序列化

class User {
    public var _name: String = ""
    public var _age: Int64 = 0
    public var active: Bool = true
    public var _role: Role = Role.Member   // 枚举 → 名字字符串
    public var opt: ?String = None         // OptionSome→值,None→null
    public var _tags: Array<String> = []
    public var addr: Address = Address()   // 嵌套对象
}

let u = User()
u._name = "alice"
u._age = 30

let json = JsonSerializer.Serialize(u)
// { "_name": "alice", "_age": 30, "active": true, "_role": "Member", "opt": null, "_tags": [], "addr": {...} }

let u2 = JsonSerializer.Deserialize<User>(json)
// 全部字段回填

类无需显式 public init() {}——编译器自动提供无参构造(反射构造已验证)。

注解

class User {
    @SerializerPropertyName["user_name"]
    public var _username: String = ""   // JSON 键用 user_name(对齐 [JsonPropertyName]

    @SerializerIgnore
    public var _temp: String = ""       // 序列化/反序列化忽略(对齐 [JsonIgnore]
}

父类字段序列化(@SerializerParent

背景

Cangjie 反射对实例成员读写有声明类严格校验declaringClass != TypeInfo.of(instance)), 父类字段无法用子类实例读写。@SerializerParent 宏在编译期生成静态导出/导入方法, 方法体内用静态类型访问字段,绕开该限制。

用法

import simcu::serialization.*
import simcu::serialization.macros.*

@SerializerParent                 // 标注在父类上;非 open 类自动补 open
class BaseUser {
    public var _id: String = ""
    public var _createdAt: String = ""
}

class User <: BaseUser {          // 子类零改动
    public var _name: String = ""
}

let u = User()
u._id = "u-1"
u._name = "alice"

let json = JsonSerializer.Serialize(u)
// 输出包含父类字段:{ "_name": "alice", "_id": "u-1", "_createdAt": "" }

宏支持任意字段名_ 前缀或无下划线均可),只需有类型注解。

特性

特性 说明
自动补 open 非 open 类标注宏后自动可继承
多层继承 沿 superClass 链逐层调用;中间层无宏自动跳过
注解生效 父类字段的 @SerializerPropertyName / @SerializerIgnore 同样生效
任意字段名 _ 前缀与无下划线字段都处理
向后兼容 无宏的类行为不变

宏生成的方法

// 宏为父类自动生成(可直接调用):
BaseUser.exportJsonFields(instance)                  // HashMap<String, Any>
BaseUser.importJsonFields(instance, json)            // 回填字段

选项(JsonOption

选项 默认 说明
propertyNamingPolicy CamelCase 字段命名策略
enumAsString true 枚举序列化为名字
maxDepth 64 递归深度上限(超过抛异常)
let opt = JsonOption()
opt.propertyNamingPolicy = PropertyNamingPolicy.SnakeCase   // userName → user_name
opt.maxDepth = 16

let json = JsonSerializer.Serialize(u, opt)

运行时类型反序列化(框架绑定用)

供框架模型绑定等场景按运行时类型反序列化(无需编译期泛型):

import std.reflect.*

let typeInfo = TypeInfo.of<MyDto>()
let obj: Any = JsonSerializer.Deserialize(typeInfo, jsonString)

命名策略(PropertyNamingPolicy

策略 效果
Keep 字段名原样(_username_username
CamelCase 首字母小写(Namename;下划线字段保持原样)
SnakeCase 大写转下划线(userNameuser_name

注:不剥除字段名前导下划线——_name 原样输出 _name

支持的类型

类别 说明
基础类型 String / Bool / 全部整数 / 浮点 / Rune
集合 Array<T> / ArrayList<T> / HashSet<T>
字典 HashMap<K, V>(键须可转字符串)
Option<T> Some(x) → 值;Nonenull
枚举 构造器名(Role.Admin"Admin"
普通类 无参构造 + var 字段;嵌套对象递归

宽松类型转换(反序列化)

JSON 数字 ↔ 字符串字段自动互转:Deserialize<String>("42")"42" Deserialize<Int64>("\"42\"")42

已知限制

  • 父类字段序列化需父类标注 @SerializerParent(见上文;Cangjie 反射平台限制)
  • 反序列化要求目标类型无参构造(编译器自动提供,无需显式写 init(){})、字段为 varlet 只读字段跳过)
  • 集合/字典元素类型需为支持的类型
  • 泛型父类暂不支持

包结构

src/
├── SimApiSerialization.cj      // 根锚点:public import common.* + json.*
├── common/                     // XML/JSON 共用
│   ├── Annotations.cj          // @SerializerPropertyName / @SerializerIgnore
│   ├── ReflectionCache.cj      // 字段元数据 + 继承链缓存
│   └── NamingPolicy.cj         // PropertyNamingPolicy
├── json/                       // JSON 序列化
│   ├── JsonSerializer.cj       // 公开 API(含 TypeInfo 版 Deserialize
│   ├── JsonWriter.cj / JsonReader.cj
│   └── JsonOption.cj
├── macros/                     // @SerializerParent 宏
│   └── SerializerParentMacro.cj
└── tests/                      // 单元测试(独立子包)
    └── JsonSerializer_test.cj  // cjpm test18 用例

测试

cjpm test
# TOTAL: 18, PASSED: 18

覆盖:基础类型、对象字段输出、注解、Option、集合、HashMap、枚举、命名策略、 父类字段(宏)、多层继承、三级继承、maxDepth、宽松类型转换。

设计参考

  • API 对齐 .NET System.Text.JsonJsonSerializer.Serialize/Deserialize + JsonSerializerOptions
  • 注解对齐 [JsonPropertyName] / [JsonIgnore]
  • 父类方案参考 soulsoft_serialization 的「宏生成静态类型字段代码」思路 (详见 docs/父类字段序列化方案.md