diff --git a/docs/父类字段序列化方案.md b/docs/父类字段序列化方案.md index 315f3af..7903897 100644 --- a/docs/父类字段序列化方案.md +++ b/docs/父类字段序列化方案.md @@ -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() ```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(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`;