docs: 宏改名为 @JsonParent——简短且与 @JsonPropertyName/@JsonIgnore 前缀风格统一

This commit is contained in:
2026-08-17 13:32:57 +08:00
parent 24c5b1e1ba
commit 00fea9703c
+15 -15
View File
@@ -136,7 +136,7 @@ BaseUser.deserializeObject(dms, data, options) // 反序列化:先回填父
```
┌─────────────────────────────────────────────────────────┐
│ 宏 @JsonExportFields(标注在父类上) │
│ 宏 @JsonParent(标注在父类上) │
│ → 编译期解析父类声明的 var 字段 │
│ → 自动生成两个静态方法(静态类型访问,无反射检查): │
│ exportJsonFields(instance: Parent) │
@@ -171,7 +171,7 @@ soulsoft 的 API 带泛型约束 `where T <: ISerializable`,不标宏的类在
### 3.1 宏定义
```cangjie
// 文件:src/json/JsonExportFieldsMacro.cj
// 文件:src/json/JsonParentMacro.cj
// 包:simapi_serialization.json(宏包需单独编译,见 3.3)
macro package simapi_serialization.json
@@ -180,7 +180,7 @@ import std.ast.*
import std.collection.*
/// 标注在父类上:自动生成父类字段的 JSON 导出/导入静态方法
public macro JsonExportFields(input: Tokens): Tokens {
public macro JsonParent(input: Tokens): Tokens {
// 1. 解析输入的 ClassDecl(非类声明 → 抛 MacroException
// 2. 校验 open:非 open class → 抛 MacroException(见 3.1.1
// 3. 收集 public var 字段(跳过 @JsonIgnore
@@ -191,7 +191,7 @@ public macro JsonExportFields(input: Tokens): Tokens {
#### 3.1.1 open 处理(两种模式,默认自动补 open)
`@JsonExportFields` 的语义是「暴露**父类**字段给子类继承链」——标注的类**必须可被继承**。Cangjie 类默认不可继承(非 open 类被继承会编译报错 `super class is not inheritable`),所以宏展开时处理 `open`
`@JsonParent` 的语义是「暴露**父类**字段给子类继承链」——标注的类**必须可被继承**。Cangjie 类默认不可继承(非 open 类被继承会编译报错 `super class is not inheritable`),所以宏展开时处理 `open`
```cangjie
/// 遍历类声明的修饰符,检查是否含 open(参考 soulsoft Extensions.cj isOpen
@@ -216,13 +216,13 @@ if (!isOpenClass(decl)) {
- **已实测可行**:宏给 `class Base` 自动加 `open` 后,子类 `class Child <: Base` 编译通过、正常运行(`macro_open_probe` 验证);
- 宏展开的 `open` 在语义检查**之前**生效,所以后续继承检查能看到;
- 用户少写一个关键字,标注 `@JsonExportFields` 本身就表达了「我要被继承」的意图。
- 用户少写一个关键字,标注 `@JsonParent` 本身就表达了「我要被继承」的意图。
**模式二:严格校验(不自动补,非 open 报错)**
```cangjie
if (!isOpenClass(decl)) {
throw ASTException("@JsonExportFields 只能标注在 open class 上,"
throw ASTException("@JsonParent 只能标注在 open class 上,"
+ "因为非 open 类不能被继承,不存在子类场景。")
}
```
@@ -230,7 +230,7 @@ if (!isOpenClass(decl)) {
-`ASTException`(宏内实际可用异常类,soulsoft 同款)→ 编译期直接报错,错误定位到标注处(`main.cj:5:1` 形式);
- 顺带校验:标注在 **struct / interface / enum / func** 等非 class 声明上也抛错(`parseDecl` 结果 `as ClassDecl` 失败即报,已实测)。
**取舍**:自动补 open 更省事但「隐式改变类语义」;严格校验更显式但要求用户记得写 `open`。默认建议模式一(自动补),可在宏属性中提供开关,如 `@JsonExportFields[requireOpen: true]` 切到模式二。
**取舍**:自动补 open 更省事但「隐式改变类语义」;严格校验更显式但要求用户记得写 `open`。默认建议模式一(自动补),可在宏属性中提供开关,如 `@JsonParent[requireOpen: true]` 切到模式二。
- 参考先例:soulsoft `Extensions.cj:75-82` 遍历 `modifiers``TokenKind.OPEN``SerializationMacro.cj:27``throw ASTException(...)` 做宏内校验;`cd.modifiers.add(Modifier(Token(TokenKind.OPEN)))` 与 soulsoft `funcDecl.modifiers.add(Modifier(Token(TokenKind.PUBLIC)))` 同款操作。
@@ -239,7 +239,7 @@ if (!isOpenClass(decl)) {
对如下父类:
```cangjie
@JsonExportFields
@JsonParent
open class BaseUser {
public var _id: String = ""
public var _createdAt: String = ""
@@ -435,10 +435,10 @@ private static let _parentImportCache = HashMap<String, Bool>()
```cangjie
import simapi_serialization.*
import simapi_serialization.json.JsonExportFields // 引入宏
import simapi_serialization.json.JsonParent // 引入宏
// 父类标注宏
@JsonExportFields
@JsonParent
open class BaseUser {
public var _id: String = ""
public var _createdAt: String = ""
@@ -484,9 +484,9 @@ main() {
| 父类字段 null | 导入时保持默认值 |
| 与 @JsonPropertyName 组合 | 父类字段用注解名输出/匹配 |
| 顶层序列化父类类型实例 | `Serialize(BaseUser 实例)` 直接可用 |
| **宏自动补 open** | `@JsonExportFields class Base`(无 open)展开后子类可继承(编译通过) |
| **宏严格模式报错** | `@JsonExportFields[requireOpen: true]` 标注非 open class 编译失败 |
| **宏非 class 标注报错** | 对 struct/interface/enum 标注 `@JsonExportFields` 编译失败 |
| **宏自动补 open** | `@JsonParent class Base`(无 open)展开后子类可继承(编译通过) |
| **宏严格模式报错** | `@JsonParent[requireOpen: true]` 标注非 open class 编译失败 |
| **宏非 class 标注报错** | 对 struct/interface/enum 标注 `@JsonParent` 编译失败 |
---
@@ -508,7 +508,7 @@ main() {
| | 路线 A:入口不变 + 父类宏(本方案) | 路线 B:soulsoft 全宏风格 |
|---|---|---|
| 宏标在哪 | **仅父类**标 `@JsonExportFields` | **每个类**标 `@Serialization[superType: 父类]` |
| 宏标在哪 | **仅父类**标 `@JsonParent` | **每个类**标 `@Serialization[superType: 父类]` |
| 继承串联 | 库运行时反射 `superClass` 链 + 静态方法调用 | 编译期 `super.serializeObject(...)` / `Parent.deserializeObject(...)` 调用链 |
| `Serialize(obj)` / `Deserialize<T>(json)` | ✅ **完全不变**(无泛型约束,任意类) | 需保留反射回退,否则无宏类编译期拒绝 |
| 无宏的类 | ✅ 照旧全反射(向后兼容) | 无法序列化(除非入口加反射回退) |
@@ -535,7 +535,7 @@ main() {
## 9. 实施步骤(评审通过后)
1. 新建宏文件 `src/json/JsonExportFieldsMacro.cj`(或独立宏包),实现 `JsonExportFields` 宏;
1. 新建宏文件 `src/json/JsonParentMacro.cj`(或独立宏包),实现 `JsonParent` 宏;
2. 验证 cjpm 对宏包的编译流程(风险 #1),必要时调整项目结构;
3.`JsonWriter.writeObject`superClass 链调用 `exportJsonFields`
4.`JsonReader.readObject`superClass 链调用 `importJsonFields`