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
+29
View File
@@ -133,9 +133,38 @@ public class JsonReader {
case None => ()
}
}
// 父类字段(@JsonParent 宏生成的静态导入方法,沿继承链逐层回填)
readParentFields(value, ct, instance, options)
instance
}
/// 沿 superClass 链调用每层的 importJsonFields 静态方法回填父类字段。
/// 无宏的父类(hasImportFields 缓存判断)静默跳过;宏生成的方法内部按
/// if (k == "字段名") 忽略未知键,因此直接把全部 JSON 键传入即可。
private static func readParentFields(value: JsonValue, ct: ClassTypeInfo, instance: Any, options: JsonOption): Unit {
let jobj = value.asObject()
var parent = ct.superClass
while (let Some(p) <- parent) {
if (ReflectionCache.hasImportFields(p)) {
try {
let fn = p.getStaticFunction("importJsonFields",
[p, TypeInfo.of<HashMap<String, Any>>()])
var pjson = HashMap<String, Any>()
for ((k, jv) in jobj.getFields()) {
if (!(jv is JsonNull)) {
pjson[k] = jsonToAny(jv)
}
}
let args: Array<Any> = [instance, pjson]
fn.apply(p, args)
} catch (_: Exception) {
// 导入失败(如类型不匹配)不中断整体反序列化
}
}
parent = p.superClass
}
}
/// Array<X>:经 ArrayList<X> 构造 + add + toArray
private static func readArray(value: JsonValue, elemName: String, options: JsonOption, depth: Int64): Any {
let listTypeName = "std.collection.ArrayList<${elemName}>"