Files
serialization-cj/README.md
T
xrain c181ada90b docs: 新增 README——快速开始/注解/父类字段宏/选项/支持类型/包结构/测试
- 单 import 全量可用:import simapi_serialization.*
- @SerializerParent 父类字段序列化用法与特性
- JsonOption 选项、命名策略、支持类型、宽松转换、已知限制
- 全部示例经 serialization_test 实测验证
2026-08-17 14:10:30 +08:00

191 lines
6.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# simapi_serialization
SimApi 全反射 JSON 序列化库(仓颉版),对齐 .NET `System.Text.Json` 的用法与注解风格。
- **免标注**:任意类(无参构造 + `var` 字段)无需实现接口、无需标注,开箱即用
- **注解**`@SerializerPropertyName` / `@SerializerIgnore`(对齐 `[JsonPropertyName]` / `[JsonIgnore]`
- **继承支持**`@SerializerParent` 宏解决父类字段序列化(Cangjie 反射限制)
- **API 对齐**`JsonSerializer.Serialize(obj, JsonOption)` / `Deserialize<T>(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 // 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": "User", "opt": null, "_tags": [], "addr": {...} }
let u2 = JsonSerializer.Deserialize<User>(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<String, Any>
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<T>` / `ArrayList<T>` / `HashSet<T>` |
| 字典 | `HashMap<K, V>`(键须可转字符串) |
| `Option<T>` | `Some(x)` → 值;`None``null` |
| 枚举 | 构造器名(`Role.Admin``"Admin"` |
| 普通类 | 无参构造 + `var` 字段;嵌套对象递归 |
### 宽松类型转换(反序列化)
JSON 数字 ↔ 字符串字段自动互转:`Deserialize<String>("42")``"42"`
`Deserialize<Int64>("\"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 test16 用例)
└── 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`