From 990f10f98c7a9bfa2c03e83544d50639df2b2c63 Mon Sep 17 00:00:00 2001 From: xRain Date: Mon, 17 Aug 2026 13:58:05 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E6=B3=A8=E8=A7=A3=E4=B8=8E?= =?UTF-8?q?=E5=AE=8F=E6=94=B9=E5=90=8D=E2=80=94=E2=80=94Serializer=20?= =?UTF-8?q?=E5=89=8D=E7=BC=80=E7=BB=9F=E4=B8=80=E5=91=BD=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - @JsonPropertyName → @SerializerPropertyName - @JsonIgnore → @SerializerIgnore - @JsonParent → @SerializerParent(宏文件 JsonParentMacro.cj → SerializerParentMacro.cj) - 同步更新:JsonAnnotations、ReflectionCache、宏内部注解判断、 测试、方案文档、serialization_test 独立项目 - 16 用例全绿 --- cjpm.toml | 2 +- docs/父类字段序列化方案.md | 46 +++++++++---------- src/SimApiSerialization.cj | 2 +- src/json/JsonAnnotations.cj | 16 +++---- src/json/JsonReader.cj | 2 +- src/json/JsonSerializer_test.cj | 36 +++++++-------- src/json/JsonWriter.cj | 4 +- src/json/ReflectionCache.cj | 22 ++++----- ...arentMacro.cj => SerializerParentMacro.cj} | 24 +++++----- 9 files changed, 77 insertions(+), 77 deletions(-) rename src/macros/{JsonParentMacro.cj => SerializerParentMacro.cj} (88%) diff --git a/cjpm.toml b/cjpm.toml index d168c9c..026bd01 100644 --- a/cjpm.toml +++ b/cjpm.toml @@ -1,7 +1,7 @@ [package] cjc-version = "1.1.3" name = "simapi_serialization" - description = "SimApi 全反射 JSON 序列化库(对齐 .NET JsonSerializer.Serialize/Deserialize + JsonPropertyName/JsonIgnore 特性)" + description = "SimApi 全反射 JSON 序列化库(对齐 .NET JsonSerializer.Serialize/Deserialize + SerializerPropertyName/SerializerIgnore 特性)" version = "1.0.0" target-dir = "" output-type = "static" diff --git a/docs/父类字段序列化方案.md b/docs/父类字段序列化方案.md index 7903897..39fdd37 100644 --- a/docs/父类字段序列化方案.md +++ b/docs/父类字段序列化方案.md @@ -136,7 +136,7 @@ BaseUser.deserializeObject(dms, data, options) // 反序列化:先回填父 ``` ┌─────────────────────────────────────────────────────────┐ -│ 宏 @JsonParent(标注在父类上) │ +│ 宏 @SerializerParent(标注在父类上) │ │ → 编译期解析父类声明的 var 字段 │ │ → 自动生成两个静态方法(静态类型访问,无反射检查): │ │ exportJsonFields(instance: Parent) │ @@ -171,7 +171,7 @@ soulsoft 的 API 带泛型约束 `where T <: ISerializable`,不标宏的类在 ### 3.1 宏定义 ```cangjie -// 文件:src/json/JsonParentMacro.cj +// 文件:src/json/SerializerParentMacro.cj // 包:simapi_serialization.json(宏包需单独编译,见 3.3) macro package simapi_serialization.json @@ -180,10 +180,10 @@ import std.ast.* import std.collection.* /// 标注在父类上:自动生成父类字段的 JSON 导出/导入静态方法 -public macro JsonParent(input: Tokens): Tokens { +public macro SerializerParent(input: Tokens): Tokens { // 1. 解析输入的 ClassDecl(非类声明 → 抛 MacroException) // 2. 校验 open:非 open class → 抛 MacroException(见 3.1.1) - // 3. 收集 public var 字段(跳过 @JsonIgnore) + // 3. 收集 public var 字段(跳过 @SerializerIgnore) // 4. 生成 exportJsonFields / importJsonFields 两个静态方法 // 5. 拼回原类声明 + 新方法,返回 Tokens } @@ -191,7 +191,7 @@ public macro JsonParent(input: Tokens): Tokens { #### 3.1.1 open 处理(两种模式,默认自动补 open) -`@JsonParent` 的语义是「暴露**父类**字段给子类继承链」——标注的类**必须可被继承**。Cangjie 类默认不可继承(非 open 类被继承会编译报错 `super class is not inheritable`),所以宏展开时处理 `open`: +`@SerializerParent` 的语义是「暴露**父类**字段给子类继承链」——标注的类**必须可被继承**。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` 在语义检查**之前**生效,所以后续继承检查能看到; -- 用户少写一个关键字,标注 `@JsonParent` 本身就表达了「我要被继承」的意图。 +- 用户少写一个关键字,标注 `@SerializerParent` 本身就表达了「我要被继承」的意图。 **模式二:严格校验(不自动补,非 open 报错)** ```cangjie if (!isOpenClass(decl)) { - throw ASTException("@JsonParent 只能标注在 open class 上," + throw ASTException("@SerializerParent 只能标注在 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`。默认建议模式一(自动补),可在宏属性中提供开关,如 `@JsonParent[requireOpen: true]` 切到模式二。 +**取舍**:自动补 open 更省事但「隐式改变类语义」;严格校验更显式但要求用户记得写 `open`。默认建议模式一(自动补),可在宏属性中提供开关,如 `@SerializerParent[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,11 +239,11 @@ if (!isOpenClass(decl)) { 对如下父类: ```cangjie -@JsonParent +@SerializerParent open class BaseUser { public var _id: String = "" public var _createdAt: String = "" - @JsonIgnore + @SerializerIgnore public var _temp: String = "" } ``` @@ -254,7 +254,7 @@ open class BaseUser { open class BaseUser { public var _id: String = "" public var _createdAt: String = "" - @JsonIgnore + @SerializerIgnore public var _temp: String = "" /// 导出:字段名 → 值(静态类型访问) @@ -262,7 +262,7 @@ open class BaseUser { var m = HashMap() m["_id"] = instance._id m["_createdAt"] = instance._createdAt - // _temp 被 @JsonIgnore 跳过 + // _temp 被 @SerializerIgnore 跳过 m } @@ -318,8 +318,8 @@ Cangjie 宏需要两步编译(`cjc --compile-macro` 先编宏,再编使用 | 细节 | 处理 | |---|---| | 字段类型 | 用 `TypeInfo.get(字段类型名)` 在运行时做类型转换(import 侧) | -| `@JsonPropertyName` | export 键用注解名;import 匹配也用注解名 | -| `@JsonIgnore` | 直接跳过,不生成导出/导入语句 | +| `@SerializerPropertyName` | export 键用注解名;import 匹配也用注解名 | +| `@SerializerIgnore` | 直接跳过,不生成导出/导入语句 | | `let`(不可变)字段 | 只导出,不导入(导入侧跳过) | | 无字段 | 生成空方法(返回空 map / 空操作),保证约定方法一定存在 | | 命名冲突 | 若用户已手写同名静态方法,宏应报错或跳过(设计取舍:报错更安全) | @@ -435,10 +435,10 @@ private static let _parentImportCache = HashMap() ```cangjie import simapi_serialization.* -import simapi_serialization.json.JsonParent // 引入宏 +import simapi_serialization.json.SerializerParent // 引入宏 // 父类标注宏 -@JsonParent +@SerializerParent open class BaseUser { public var _id: String = "" public var _createdAt: String = "" @@ -474,7 +474,7 @@ main() { | 用例 | 断言 | |---|---| -| 父类字段序列化 | 输出包含 `_id`/`_createdAt`,且 `@JsonIgnore` 父类字段不输出 | +| 父类字段序列化 | 输出包含 `_id`/`_createdAt`,且 `@SerializerIgnore` 父类字段不输出 | | 父类字段反序列化 | `Deserialize` 后父类字段值正确 | | 多层继承 | GrandParent → Parent → Child 三层字段全部输出 | | 中间层无宏 | 三层链中 Parent 不标宏:`_gp` 仍导出,`_p` 不导出(逐层跳过) | @@ -482,11 +482,11 @@ main() { | 子类字段与父类字段重名 | 子类优先(输出一份,值取子类的) | | 父类嵌套对象字段 | 父类字段值是对象时正确递归 | | 父类字段 null | 导入时保持默认值 | -| 与 @JsonPropertyName 组合 | 父类字段用注解名输出/匹配 | +| 与 @SerializerPropertyName 组合 | 父类字段用注解名输出/匹配 | | 顶层序列化父类类型实例 | `Serialize(BaseUser 实例)` 直接可用 | -| **宏自动补 open** | `@JsonParent class Base`(无 open)展开后子类可继承(编译通过) | -| **宏严格模式报错** | `@JsonParent[requireOpen: true]` 标注非 open class 编译失败 | -| **宏非 class 标注报错** | 对 struct/interface/enum 标注 `@JsonParent` 编译失败 | +| **宏自动补 open** | `@SerializerParent class Base`(无 open)展开后子类可继承(编译通过) | +| **宏严格模式报错** | `@SerializerParent[requireOpen: true]` 标注非 open class 编译失败 | +| **宏非 class 标注报错** | 对 struct/interface/enum 标注 `@SerializerParent` 编译失败 | --- @@ -508,7 +508,7 @@ main() { | | 路线 A:入口不变 + 父类宏(本方案) | 路线 B:soulsoft 全宏风格 | |---|---|---| -| 宏标在哪 | **仅父类**标 `@JsonParent` | **每个类**标 `@Serialization[superType: 父类]` | +| 宏标在哪 | **仅父类**标 `@SerializerParent` | **每个类**标 `@Serialization[superType: 父类]` | | 继承串联 | 库运行时反射 `superClass` 链 + 静态方法调用 | 编译期 `super.serializeObject(...)` / `Parent.deserializeObject(...)` 调用链 | | `Serialize(obj)` / `Deserialize(json)` | ✅ **完全不变**(无泛型约束,任意类) | 需保留反射回退,否则无宏类编译期拒绝 | | 无宏的类 | ✅ 照旧全反射(向后兼容) | 无法序列化(除非入口加反射回退) | @@ -535,7 +535,7 @@ main() { ## 9. 实施步骤(评审通过后) -1. 新建宏文件 `src/json/JsonParentMacro.cj`(或独立宏包),实现 `JsonParent` 宏; +1. 新建宏文件 `src/json/SerializerParentMacro.cj`(或独立宏包),实现 `SerializerParent` 宏; 2. 验证 cjpm 对宏包的编译流程(风险 #1),必要时调整项目结构; 3. 改 `JsonWriter.writeObject`:superClass 链调用 `exportJsonFields`; 4. 改 `JsonReader.readObject`:superClass 链调用 `importJsonFields`; diff --git a/src/SimApiSerialization.cj b/src/SimApiSerialization.cj index bba8765..d523683 100644 --- a/src/SimApiSerialization.cj +++ b/src/SimApiSerialization.cj @@ -4,7 +4,7 @@ * simapi_serialization 根包锚点(cjpm 要求 src 根目录至少有一个 .cj 文件,否则不扫描子目录)。 * 全部实现位于子包 simapi_serialization.json(对应 .NET System.Text.Json)。 * 通过 public import 重导出:`import simapi_serialization.*` 仍可直接使用 - * JsonSerializer / JsonOption / @JsonPropertyName / @JsonIgnore 等。 + * JsonSerializer / JsonOption / @SerializerPropertyName / @SerializerIgnore 等。 */ package simapi_serialization diff --git a/src/json/JsonAnnotations.cj b/src/json/JsonAnnotations.cj index 7de1673..fe689bc 100644 --- a/src/json/JsonAnnotations.cj +++ b/src/json/JsonAnnotations.cj @@ -1,8 +1,8 @@ /* * Copyright (c) 2025 SimcuTeam. All rights reserved. * 对齐 .NET System.Text.Json.Serialization 特性: - * - [JsonPropertyName("xxx")] → @JsonPropertyName["xxx"] 指定字段的 JSON 名称 - * - [JsonIgnore] → @JsonIgnore 序列化/反序列化时忽略该字段 + * - [SerializerPropertyName("xxx")] → @SerializerPropertyName["xxx"] 指定字段的 JSON 名称 + * - [SerializerIgnore] → @SerializerIgnore 序列化/反序列化时忽略该字段 * * 设计决策:本库序列化/反序列化只处理「var 成员变量」(std.reflect 的 instanceVariables), * 不处理 prop 属性(instanceProperties)。因此注解 target 仅限 MemberVariable: @@ -15,11 +15,11 @@ package simapi_serialization.json /** - * 指定字段的 JSON 名称(对齐 .NET JsonPropertyNameAttribute)。 - * 用法:@JsonPropertyName["user_name"] public var _username: String = "" + * 指定字段的 JSON 名称(对齐 .NET SerializerPropertyNameAttribute)。 + * 用法:@SerializerPropertyName["user_name"] public var _username: String = "" */ @Annotation[target: [MemberVariable]] -public class JsonPropertyName { +public class SerializerPropertyName { public let name: String public const init(name: String) { @@ -28,10 +28,10 @@ public class JsonPropertyName { } /** - * 标记字段不做 JSON 处理(对齐 .NET JsonIgnoreAttribute)。 - * 用法:@JsonIgnore public var _temp: String = "" + * 标记字段不做 JSON 处理(对齐 .NET SerializerIgnoreAttribute)。 + * 用法:@SerializerIgnore public var _temp: String = "" */ @Annotation[target: [MemberVariable]] -public class JsonIgnore { +public class SerializerIgnore { public const init() {} } diff --git a/src/json/JsonReader.cj b/src/json/JsonReader.cj index 29ccbaf..45ba25e 100644 --- a/src/json/JsonReader.cj +++ b/src/json/JsonReader.cj @@ -133,7 +133,7 @@ public class JsonReader { case None => () } } - // 父类字段(@JsonParent 宏生成的静态导入方法,沿继承链逐层回填) + // 父类字段(@SerializerParent 宏生成的静态导入方法,沿继承链逐层回填) readParentFields(value, ct, instance, options) instance } diff --git a/src/json/JsonSerializer_test.cj b/src/json/JsonSerializer_test.cj index f473741..e39ad95 100644 --- a/src/json/JsonSerializer_test.cj +++ b/src/json/JsonSerializer_test.cj @@ -1,7 +1,7 @@ /* * Copyright (c) 2025 SimcuTeam. All rights reserved. * JsonSerializer 单元测试(cjpm test)。 - * 覆盖:基础类型 / 对象字段输出 / 注解(JsonPropertyName、JsonIgnore)/ Option / + * 覆盖:基础类型 / 对象字段输出 / 注解(SerializerPropertyName、SerializerIgnore)/ Option / * 集合(Array、ArrayList、HashSet)/ HashMap / 枚举 / 命名策略 / * 继承(平台限制)/ maxDepth / 宽松类型转换。 * @@ -27,15 +27,15 @@ class Address { public var zip: String = "" // 无下划线 → 原样输出 zip } -// 继承测试:父类标注 @JsonParent 宏 → 自动补 open + 生成导出/导入静态方法, +// 继承测试:父类标注 @SerializerParent 宏 → 自动补 open + 生成导出/导入静态方法, // 父类字段(_id/_createdAt)经宏的静态类型访问绕开反射声明类校验 -@JsonParent +@SerializerParent open class BaseUser { public var _id: String = "" public var _createdAt: String = "" - @JsonIgnore + @SerializerIgnore public var _temp: String = "" - @JsonPropertyName["parent_alias"] + @SerializerPropertyName["parent_alias"] public var _parentAlias: String = "" } @@ -49,14 +49,14 @@ class User <: BaseUser { public var remark: ?String = None // 无下划线(Option=None → null) public var _tags: Array = [] // 下划线字段(集合) public var addr: Address = Address() // 无下划线(嵌套对象) - @JsonPropertyName["user_alias"] + @SerializerPropertyName["user_alias"] public var _alias: String = "" // 下划线 + 注解覆盖 - @JsonIgnore + @SerializerIgnore public var temp: String = "secret" // 无下划线 + 忽略 } // 多层继承:爷(标宏)→ 父(不标宏)→ 子 -@JsonParent +@SerializerParent open class GrandParent { public var _gp: String = "" } @@ -129,10 +129,10 @@ public class JsonSerializerTests { // 无下划线字段原样输出 @Expect(json.contains("\"score\""), true) @Expect(json.contains("\"active\": true"), true) - // @JsonPropertyName 覆盖字段名 + // @SerializerPropertyName 覆盖字段名 @Expect(json.contains("\"user_alias\": \"xiaoming\""), true) @Expect(json.contains("\"_alias\""), false) - // @JsonIgnore 字段不输出 + // @SerializerIgnore 字段不输出 @Expect(json.contains("temp"), false) @Expect(json.contains("\"secret\""), false) // Option:Some→值,None→null @@ -143,13 +143,13 @@ public class JsonSerializerTests { // 嵌套对象 @Expect(json.contains("\"_city\": \"beijing\""), true) @Expect(json.contains("\"zip\": \"100000\""), true) - // 父类字段(@JsonParent 宏):_id/_createdAt 输出,@JsonIgnore 父类字段不输出 + // 父类字段(@SerializerParent 宏):_id/_createdAt 输出,@SerializerIgnore 父类字段不输出 @Expect(json.contains("\"_id\": \"u-1\""), true) @Expect(json.contains("\"_createdAt\": \"2025-01-01\""), true) - // 父类 @JsonPropertyName["parent_alias"] 生效 + // 父类 @SerializerPropertyName["parent_alias"] 生效 @Expect(json.contains("\"parent_alias\": \"parent-xiaoming\""), true) @Expect(json.contains("_parentAlias"), false) - // 父类 @JsonIgnore _temp 不输出 + // 父类 @SerializerIgnore _temp 不输出 @Expect(json.contains("secret-parent"), false) } @@ -165,8 +165,8 @@ public class JsonSerializerTests { @Expect(u2.addr._city, "beijing") @Expect(u2.addr.zip, "100000") @Expect(u2._alias, "xiaoming") - @Expect(u2.temp, "secret") // @JsonIgnore:反序列化不改动默认值 - // 父类字段往返(@JsonParent 宏) + @Expect(u2.temp, "secret") // @SerializerIgnore:反序列化不改动默认值 + // 父类字段往返(@SerializerParent 宏) @Expect(u2._id, "u-1") @Expect(u2._createdAt, "2025-01-01") @Expect(u2._parentAlias, "parent-xiaoming") @@ -322,7 +322,7 @@ public class JsonSerializerTests { @Expect(threw, true) } - /// 父类字段序列化/反序列化(@JsonParent 宏):已并入 objectSerialize/objectRoundTrip, + /// 父类字段序列化/反序列化(@SerializerParent 宏):已并入 objectSerialize/objectRoundTrip, /// 此处验证宏生成的静态方法可直接调用 @TestCase public func parentMacroMethods() { @@ -335,7 +335,7 @@ public class JsonSerializerTests { @Expect(toStr(m["_id"]), "m-1") @Expect(toStr(m["_createdAt"]), "2025-02-02") @Expect(toStr(m["parent_alias"]), "alias-m") - // @JsonIgnore 父类字段不导出 + // @SerializerIgnore 父类字段不导出 @Expect(m.contains("_temp"), false) // 宏生成的导入方法 var json = HashMap() @@ -366,7 +366,7 @@ public class JsonSerializerTests { @Expect(back._mp, "") // 中间层字段保持默认值 } - /// 宏自动补 open:GrandParent 未显式写 open(@JsonParent 自动补),继承链可正常编译 + /// 宏自动补 open:GrandParent 未显式写 open(@SerializerParent 自动补),继承链可正常编译 @TestCase public func parentAutoOpen() { let leaf = LeafChild() diff --git a/src/json/JsonWriter.cj b/src/json/JsonWriter.cj index cd541e1..7c518c9 100644 --- a/src/json/JsonWriter.cj +++ b/src/json/JsonWriter.cj @@ -106,14 +106,14 @@ public class JsonWriter { // 1) 子类自身字段(反射) let fields = ReflectionCache.getFields(ct, options) for (f in fields) { - // 只要不是 @JsonIgnore 的字段一律输出;None 字段输出 null + // 只要不是 @SerializerIgnore 的字段一律输出;None 字段输出 null if (f.ignore) { continue } let raw = f.variable.getOrThrow().getValue(value) obj.put(f.jsonName, writeValue(raw, options, depth + 1)) } - // 2) 父类字段(@JsonParent 宏生成的静态导出方法,沿继承链逐层调用) + // 2) 父类字段(@SerializerParent 宏生成的静态导出方法,沿继承链逐层调用) writeParentFields(value, ct, obj, options, depth) obj } diff --git a/src/json/ReflectionCache.cj b/src/json/ReflectionCache.cj index 5bf9488..4ccc154 100644 --- a/src/json/ReflectionCache.cj +++ b/src/json/ReflectionCache.cj @@ -1,6 +1,6 @@ /* * Copyright (c) 2025 SimcuTeam. All rights reserved. - * ReflectionCache:字段元数据(含继承链、命名策略、@JsonPropertyName/@JsonIgnore)与缓存。 + * ReflectionCache:字段元数据(含继承链、命名策略、@SerializerPropertyName/@SerializerIgnore)与缓存。 * * 已知限制(平台级): * - InstanceVariableInfo.getValue/setValue 有「声明类严格类型校验」,父类字段无法用子类实例读写, @@ -18,9 +18,9 @@ import std.reflect.* public class FieldMetadata { /// 反射字段名(如 _name) public var name: String = "" - /// JSON 名称(@JsonPropertyName 优先,否则按命名策略) + /// JSON 名称(@SerializerPropertyName 优先,否则按命名策略) public var jsonName: String = "" - /// 是否忽略(@JsonIgnore) + /// 是否忽略(@SerializerIgnore) public var ignore: Bool = false /// 字段类型 public var typeInfo: ?TypeInfo = None @@ -40,20 +40,20 @@ public class ReflectionCache { private static let _cache = HashMap>() - /// 类型 → 是否有 @JsonParent 宏生成的 exportJsonFields(Bool) + /// 类型 → 是否有 @SerializerParent 宏生成的 exportJsonFields(Bool) private static let _exportCache = HashMap() - /// 类型 → 是否有 @JsonParent 宏生成的 importJsonFields(Bool) + /// 类型 → 是否有 @SerializerParent 宏生成的 importJsonFields(Bool) private static let _importCache = HashMap() /** - * 该类型是否含 @JsonParent 宏生成的导出静态方法(含缓存)。 + * 该类型是否含 @SerializerParent 宏生成的导出静态方法(含缓存)。 */ public static func hasExportFields(typeInfo: ClassTypeInfo): Bool { hasParentMethod(typeInfo, "exportJsonFields", _exportCache) } /** - * 该类型是否含 @JsonParent 宏生成的导入静态方法(含缓存)。 + * 该类型是否含 @SerializerParent 宏生成的导入静态方法(含缓存)。 */ public static func hasImportFields(typeInfo: ClassTypeInfo): Bool { hasParentMethod(typeInfo, "importJsonFields", _importCache) @@ -96,13 +96,13 @@ public class ReflectionCache { meta.variable = Some(v) meta.typeInfo = Some(v.typeInfo) meta.mutable = v.isMutable() - // @JsonIgnore - if (v.findAnnotation().isSome()) { + // @SerializerIgnore + if (v.findAnnotation().isSome()) { meta.ignore = true } - // @JsonPropertyName 优先 + // @SerializerPropertyName 优先 var jsonName = "" - if (let Some(jsonProp) <- v.findAnnotation()) { + if (let Some(jsonProp) <- v.findAnnotation()) { jsonName = jsonProp.name } else { jsonName = applyNamingPolicy(v.name, options.propertyNamingPolicy) diff --git a/src/macros/JsonParentMacro.cj b/src/macros/SerializerParentMacro.cj similarity index 88% rename from src/macros/JsonParentMacro.cj rename to src/macros/SerializerParentMacro.cj index a4a3406..d4d954a 100644 --- a/src/macros/JsonParentMacro.cj +++ b/src/macros/SerializerParentMacro.cj @@ -1,6 +1,6 @@ /* * Copyright (c) 2025 SimcuTeam. All rights reserved. - * @JsonParent:标注在父类上,自动生成父类字段的 JSON 导出/导入静态方法。 + * @SerializerParent:标注在父类上,自动生成父类字段的 JSON 导出/导入静态方法。 * * 背景:Cangjie 反射对实例成员的读写有「声明类严格校验」 * (declaringClass != TypeInfo.of(instance)),父类字段无法用子类实例 @@ -9,12 +9,12 @@ * 调用约定静态方法(见 JsonWriter/JsonReader)。 * * 用法: - * @JsonParent + * @SerializerParent * class BaseUser { * public var _id: String = "" - * @JsonPropertyName["userId"] + * @SerializerPropertyName["userId"] * public var _userId: String = "" - * @JsonIgnore + * @SerializerIgnore * public var _temp: String = "" * } * @@ -22,7 +22,7 @@ * - 非 open class 自动补 open * - 生成 exportJsonFields(instance: T): HashMap * - 生成 importJsonFields(instance: T, json: HashMap): Unit - * - @JsonIgnore 字段跳过;@JsonPropertyName 用注解名做 JSON 键 + * - @SerializerIgnore 字段跳过;@SerializerPropertyName 用注解名做 JSON 键 */ macro package simapi_serialization.macros @@ -52,7 +52,7 @@ private class FieldInfo { * @param input 被标注的类声明。 * @return 注入静态方法后的类声明。 */ -public macro JsonParent(input: Tokens): Tokens { +public macro SerializerParent(input: Tokens): Tokens { let decl = parseDecl(input) if (let cd: ClassDecl <- decl) { // 1. open 处理:自动补 open(类被标注即表达「要被继承」的意图) @@ -82,10 +82,10 @@ public macro JsonParent(input: Tokens): Tokens { return cd.toTokens() } - throw ASTException("@JsonParent 只能标注在 class 声明上(不支持 struct/interface/enum)") + throw ASTException("@SerializerParent 只能标注在 class 声明上(不支持 struct/interface/enum)") } -/// 收集类体内的可序列化字段(_ 前缀 + 类型注解;跳过 @JsonIgnore;@JsonPropertyName 用注解名) +/// 收集类体内的可序列化字段(_ 前缀 + 类型注解;跳过 @SerializerIgnore;@SerializerPropertyName 用注解名) private func collectFields(cd: ClassDecl): ArrayList { var result = ArrayList() for (d in cd.body.decls) { @@ -96,13 +96,13 @@ private func collectFields(cd: ClassDecl): ArrayList { vd.declType.toTokens().toString(), vd.keyword.kind == TokenKind.VAR)) } case md: MacroExpandDecl => - // 带注解的字段:@JsonIgnore 跳过;@JsonPropertyName["x"] 取注解名 - if (md.identifier.value == "JsonIgnore") { + // 带注解的字段:@SerializerIgnore 跳过;@SerializerPropertyName["x"] 取注解名 + if (md.identifier.value == "SerializerIgnore") { continue } if (let Some(inner) <- unwrapMacroField(md)) { if (isSerializableField(inner)) { - let jsonName = if (md.identifier.value == "JsonPropertyName") { + let jsonName = if (md.identifier.value == "SerializerPropertyName") { // 属性 tokens 形如 "user_alias"(带引号),去掉两端引号 stripQuotes(md.macroAttrs.toString()) } else { @@ -144,7 +144,7 @@ private class FieldVisitor <: Visitor { } } -/// 去掉字符串两端引号(JsonPropertyName 属性 tokens 形如 "user_alias") +/// 去掉字符串两端引号(SerializerPropertyName 属性 tokens 形如 "user_alias") private func stripQuotes(s: String): String { if (s.size >= 2 && s[0..1] == "\"" && s[s.size - 1..] == "\"") { return s[1..s.size - 1]