feat: 实现 @JsonParent 宏——父类字段序列化/反序列化支持

- 新增 src/macros/JsonParentMacro.cj(macro package simapi_serialization.macros):
  标注父类自动补 open,收集 public var 字段(跳过 @JsonIgnore,
  @JsonPropertyName 用注解名),字符串拼接生成静态方法:
    exportJsonFields(instance: T): HashMap<String, Any>
    importJsonFields(instance: T, json: HashMap<String, Any>): Unit
- JsonWriter.writeParentFields:沿 superClass 链调用 exportJsonFields 合并父类字段
- JsonReader.readParentFields:沿 superClass 链调用 importJsonFields 回填父类字段
- ReflectionCache 增加 hasExportFields/hasImportFields 缓存(避免每次反射查找)
- 测试:16 用例全绿——新增 parentMacroMethods、multiLevelInheritance、
  parentAutoOpen;更新 objectSerialize/objectRoundTrip 断言父类字段输出
This commit is contained in:
2026-08-17 13:41:16 +08:00
parent 00fea9703c
commit affadac6c2
5 changed files with 372 additions and 4 deletions
+27
View File
@@ -103,6 +103,7 @@ public class JsonWriter {
private static func writeObject(value: Any, ct: ClassTypeInfo, options: JsonOption, depth: Int64): JsonValue {
let obj = JsonObject()
// 1) 子类自身字段(反射)
let fields = ReflectionCache.getFields(ct, options)
for (f in fields) {
// 只要不是 @JsonIgnore 的字段一律输出;None 字段输出 null
@@ -112,9 +113,35 @@ public class JsonWriter {
let raw = f.variable.getOrThrow().getValue(value)
obj.put(f.jsonName, writeValue(raw, options, depth + 1))
}
// 2) 父类字段(@JsonParent 宏生成的静态导出方法,沿继承链逐层调用)
writeParentFields(value, ct, obj, options, depth)
obj
}
/// 沿 superClass 链调用每层的 exportJsonFields 静态方法并合并进 JSON。
/// 无宏的父类(hasExportFields 缓存判断)静默跳过,继续向祖父层查找。
private static func writeParentFields(value: Any, ct: ClassTypeInfo, obj: JsonObject, options: JsonOption,
depth: Int64): Unit {
var parent = ct.superClass
while (let Some(p) <- parent) {
if (ReflectionCache.hasExportFields(p)) {
try {
let f = p.getStaticFunction("exportJsonFields", [p])
let args: Array<Any> = [value] // 子类实例作父类类型参数
let m = f.apply(p, args)
if (let h: HashMap<String, Any> <- m) {
for ((k, v) in h) {
obj.put(k, writeValue(v, options, depth + 1))
}
}
} catch (_: Exception) {
// 调用失败(不应发生)→ 跳过该层
}
}
parent = p.superClass
}
}
/// 反射迭代集合:优先 toArray 转数组再 get(index);无 toArray(如 Array)直接用原集合
private static func forEachElement(collection: Any, action: (Any) -> Unit): Unit {
let ti = TypeInfo.of(collection)