From c181ada90b7cff981419545e53cf384febfa46ed Mon Sep 17 00:00:00 2001 From: xRain Date: Mon, 17 Aug 2026 14:10:30 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E6=96=B0=E5=A2=9E=20README=E2=80=94?= =?UTF-8?q?=E2=80=94=E5=BF=AB=E9=80=9F=E5=BC=80=E5=A7=8B/=E6=B3=A8?= =?UTF-8?q?=E8=A7=A3/=E7=88=B6=E7=B1=BB=E5=AD=97=E6=AE=B5=E5=AE=8F/?= =?UTF-8?q?=E9=80=89=E9=A1=B9/=E6=94=AF=E6=8C=81=E7=B1=BB=E5=9E=8B/?= =?UTF-8?q?=E5=8C=85=E7=BB=93=E6=9E=84/=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 单 import 全量可用:import simapi_serialization.* - @SerializerParent 父类字段序列化用法与特性 - JsonOption 选项、命名策略、支持类型、宽松转换、已知限制 - 全部示例经 serialization_test 实测验证 --- README.md | 190 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..55559b3 --- /dev/null +++ b/README.md @@ -0,0 +1,190 @@ +# simapi_serialization + +SimApi 全反射 JSON 序列化库(仓颉版),对齐 .NET `System.Text.Json` 的用法与注解风格。 + +- **免标注**:任意类(无参构造 + `var` 字段)无需实现接口、无需标注,开箱即用 +- **注解**:`@SerializerPropertyName` / `@SerializerIgnore`(对齐 `[JsonPropertyName]` / `[JsonIgnore]`) +- **继承支持**:`@SerializerParent` 宏解决父类字段序列化(Cangjie 反射限制) +- **API 对齐**:`JsonSerializer.Serialize(obj, JsonOption)` / `Deserialize(json, JsonOption)` + +## 快速开始 + +### 引入 + +```toml +[dependencies] +simapi_serialization = { path = "../simapi-serialization" } +``` + +```cangjie +import simapi_serialization.* // 一个 import 全量可用(注解 + 序列化器) +``` + +### 序列化 / 反序列化 + +```cangjie +class User { + public var _name: String = "" + public var _age: Int64 = 0 + public var active: Bool = true + public var _role: Role = Role.User // 枚举 → 名字字符串 + public var opt: ?String = None // Option:Some→值,None→null + public var _tags: Array = [] + 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": "User", "opt": null, "_tags": [], "addr": {...} } + +let u2 = JsonSerializer.Deserialize(json) +// 全部字段回填 +``` + +### 注解 + +```cangjie +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` 宏在编译期生成静态导出/导入方法, +方法体内用静态类型访问字段,绕开该限制。 + +### 用法 + +```cangjie +import simapi_serialization.* +import simapi_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` 同样生效 | +| 向后兼容 | 无宏的类行为不变 | + +### 宏生成的方法 + +```cangjie +// 宏为父类自动生成(可直接调用): +BaseUser.exportJsonFields(instance) // HashMap +BaseUser.importJsonFields(instance, json) // 回填字段 +``` + +## 选项(JsonOption) + +| 选项 | 默认 | 说明 | +|---|---|---| +| `propertyNamingPolicy` | `CamelCase` | 字段命名策略 | +| `enumAsString` | `true` | 枚举序列化为名字 | +| `maxDepth` | `64` | 递归深度上限(超过抛异常) | + +```cangjie +let opt = JsonOption() +opt.propertyNamingPolicy = PropertyNamingPolicy.SnakeCase // userName → user_name +opt.maxDepth = 16 + +let json = JsonSerializer.Serialize(u, opt) +``` + +### 命名策略(PropertyNamingPolicy) + +| 策略 | 效果 | +|---|---| +| `Keep` | 字段名原样(`_username` → `_username`) | +| `CamelCase` | 首字母小写(`Name` → `name`;下划线字段保持原样) | +| `SnakeCase` | 大写转下划线(`userName` → `user_name`) | + +> 注:不剥除字段名前导下划线——`_name` 原样输出 `_name`。 + +## 支持的类型 + +| 类别 | 说明 | +|---|---| +| 基础类型 | `String` / `Bool` / 全部整数 / 浮点 / `Rune` | +| 集合 | `Array` / `ArrayList` / `HashSet` | +| 字典 | `HashMap`(键须可转字符串) | +| `Option` | `Some(x)` → 值;`None` → `null` | +| 枚举 | 构造器名(`Role.Admin` → `"Admin"`) | +| 普通类 | 无参构造 + `var` 字段;嵌套对象递归 | + +### 宽松类型转换(反序列化) + +JSON 数字 ↔ 字符串字段自动互转:`Deserialize("42")` → `"42"`, +`Deserialize("\"42\"")` → `42`。 + +## 已知限制 + +- 父类字段序列化需父类标注 `@SerializerParent`(见上文;Cangjie 反射平台限制) +- 反序列化要求目标类型**无参构造**、字段为 `var`(`let` 只读字段跳过) +- 集合/字典元素类型需为支持的类型 +- 泛型父类暂不支持 + +## 包结构 + +``` +src/ +├── SimApiSerialization.cj // 根锚点:public import common.* + json.* +├── common/ // XML/JSON 共用 +│ ├── Annotations.cj // @SerializerPropertyName / @SerializerIgnore +│ ├── ReflectionCache.cj // 字段元数据 + 继承链缓存 +│ └── NamingPolicy.cj // PropertyNamingPolicy +├── json/ // JSON 序列化 +│ ├── JsonSerializer.cj // 公开 API +│ ├── JsonWriter.cj / JsonReader.cj +│ ├── JsonOption.cj +│ └── JsonSerializer_test.cj // 单元测试(cjpm test,16 用例) +└── macros/ // @SerializerParent 宏 + └── SerializerParentMacro.cj +``` + +## 测试 + +```bash +cjpm test +# TOTAL: 16, PASSED: 16 +``` + +覆盖:基础类型、对象字段输出、注解、Option、集合、HashMap、枚举、命名策略、 +父类字段(宏)、多层继承、maxDepth、宽松类型转换。 + +## 设计参考 + +- API 对齐 .NET `System.Text.Json`(`JsonSerializer.Serialize/Deserialize` + `JsonSerializerOptions`) +- 注解对齐 `[JsonPropertyName]` / `[JsonIgnore]` +- 父类方案参考 soulsoft_serialization 的「宏生成静态类型字段代码」思路 + (详见 `docs/父类字段序列化方案.md`)