docs: 新增 README——快速开始/注解/父类字段宏/选项/支持类型/包结构/测试
- 单 import 全量可用:import simapi_serialization.* - @SerializerParent 父类字段序列化用法与特性 - JsonOption 选项、命名策略、支持类型、宽松转换、已知限制 - 全部示例经 serialization_test 实测验证
This commit is contained in:
@@ -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<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 // Option:Some→值,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 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`)
|
||||
Reference in New Issue
Block a user