2026-08-17 10:47:46 +08:00
|
|
|
|
/*
|
|
|
|
|
|
* Copyright (c) 2025 SimcuTeam. All rights reserved.
|
|
|
|
|
|
* JsonWriter:对象 → JsonValue(全反射)。
|
|
|
|
|
|
*
|
|
|
|
|
|
* 集合处理:仓颉泛型是不变的(Array<String> 不能 cast 为 Array<Any>),
|
|
|
|
|
|
* 因此通过反射调用 iterator()/hasNext()/next() 与 keys()/get() 迭代元素。
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
2026-08-17 11:03:01 +08:00
|
|
|
|
package simapi_serialization.json
|
2026-08-17 10:47:46 +08:00
|
|
|
|
|
|
|
|
|
|
import std.collection.*
|
|
|
|
|
|
import std.reflect.*
|
|
|
|
|
|
import stdx.encoding.json.*
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 对象 → JsonValue 写入器。
|
|
|
|
|
|
*/
|
|
|
|
|
|
public class JsonWriter {
|
|
|
|
|
|
private init() {}
|
|
|
|
|
|
|
|
|
|
|
|
public static func write(obj: Any, options: JsonOption): JsonValue {
|
|
|
|
|
|
writeValue(obj, options, 0)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private static func writeValue(value: Any, options: JsonOption, depth: Int64): JsonValue {
|
|
|
|
|
|
if (depth > options.maxDepth) {
|
|
|
|
|
|
throw Exception("JsonSerializer: 超过最大递归深度 ${options.maxDepth}")
|
|
|
|
|
|
}
|
|
|
|
|
|
// 基本类型(快路径)
|
|
|
|
|
|
if (let s: String <- value) { return JsonString(s) }
|
|
|
|
|
|
if (let b: Bool <- value) { return JsonBool(b) }
|
|
|
|
|
|
if (let i: Int64 <- value) { return JsonInt(i) }
|
|
|
|
|
|
if (let f: Float64 <- value) { return JsonFloat(f) }
|
|
|
|
|
|
if (let i32: Int32 <- value) { return JsonInt(Int64(i32)) }
|
|
|
|
|
|
if (let i16: Int16 <- value) { return JsonInt(Int64(i16)) }
|
|
|
|
|
|
if (let i8: Int8 <- value) { return JsonInt(Int64(i8)) }
|
|
|
|
|
|
if (let u8: UInt8 <- value) { return JsonInt(Int64(u8)) }
|
|
|
|
|
|
if (let u16: UInt16 <- value) { return JsonInt(Int64(u16)) }
|
|
|
|
|
|
if (let u32: UInt32 <- value) { return JsonInt(Int64(u32)) }
|
|
|
|
|
|
if (let u64: UInt64 <- value) { return JsonInt(Int64(u64)) }
|
|
|
|
|
|
if (let f32: Float32 <- value) { return JsonFloat(Float64(f32)) }
|
|
|
|
|
|
if (let c: Rune <- value) { return JsonString("${c}") }
|
|
|
|
|
|
|
|
|
|
|
|
let typeName = TypeInfo.of(value).toString()
|
|
|
|
|
|
|
|
|
|
|
|
// Option 值(Some(x) / None):仓颉 Option 是泛型枚举,用 destruct 取关联值
|
|
|
|
|
|
if (typeName.startsWith("Option<")) {
|
|
|
|
|
|
if (let Some(inner) <- unwrapOptionValue(value)) {
|
|
|
|
|
|
return writeValue(inner, options, depth + 1)
|
|
|
|
|
|
}
|
|
|
|
|
|
return JsonNull()
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 集合:Array / ArrayList / HashSet(统一反射迭代)
|
|
|
|
|
|
if (typeName.startsWith("Array<") || typeName.startsWith("std.collection.ArrayList<") ||
|
|
|
|
|
|
typeName.startsWith("std.collection.HashSet<")) {
|
|
|
|
|
|
return writeCollection(value, options, depth)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// HashMap<String, V>
|
|
|
|
|
|
if (typeName.startsWith("std.collection.HashMap<")) {
|
|
|
|
|
|
return writeHashMap(value, options, depth)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
let ti2 = TypeInfo.of(value)
|
|
|
|
|
|
|
|
|
|
|
|
// 枚举:destruct 取构造器名
|
|
|
|
|
|
if (let et: EnumTypeInfo <- ti2) {
|
|
|
|
|
|
let (ctor, _) = et.destruct(value)
|
|
|
|
|
|
return JsonString(ctor.name)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 对象:反射字段
|
|
|
|
|
|
if (let ct: ClassTypeInfo <- ti2) {
|
|
|
|
|
|
return writeObject(value, ct, options, depth)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
throw Exception("JsonSerializer: 不支持的类型 ${typeName}")
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private static func writeCollection(value: Any, options: JsonOption, depth: Int64): JsonValue {
|
|
|
|
|
|
let arr = JsonArray()
|
|
|
|
|
|
forEachElement(value) { elem =>
|
|
|
|
|
|
arr.add(writeValue(elem, options, depth + 1))
|
|
|
|
|
|
}
|
|
|
|
|
|
arr
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private static func writeHashMap(value: Any, options: JsonOption, depth: Int64): JsonValue {
|
|
|
|
|
|
let obj = JsonObject()
|
|
|
|
|
|
let ti = TypeInfo.of(value)
|
|
|
|
|
|
let typeName = ti.toString()
|
|
|
|
|
|
let args = extractTypeArgs(typeName)
|
|
|
|
|
|
let keyType = if (args.size > 0) { TypeInfo.get(args[0]) } else { TypeInfo.of<String>() }
|
|
|
|
|
|
let getFunc = ti.getInstanceFunction("get", [keyType])
|
|
|
|
|
|
let keys = ti.getInstanceFunction("keys", []).apply(value, [])
|
|
|
|
|
|
forEachElement(keys) { k =>
|
|
|
|
|
|
let v = getFunc.apply(value, [k])
|
|
|
|
|
|
obj.put(toKeyString(k), writeValue(v, options, depth + 1))
|
|
|
|
|
|
}
|
|
|
|
|
|
obj
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private static func writeObject(value: Any, ct: ClassTypeInfo, options: JsonOption, depth: Int64): JsonValue {
|
|
|
|
|
|
let obj = JsonObject()
|
|
|
|
|
|
let fields = ReflectionCache.getFields(ct, options)
|
|
|
|
|
|
for (f in fields) {
|
2026-08-17 11:21:56 +08:00
|
|
|
|
// 只要不是 @JsonIgnore 的字段一律输出;None 字段输出 null
|
2026-08-17 10:47:46 +08:00
|
|
|
|
if (f.ignore) {
|
|
|
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
|
|
|
let raw = f.variable.getOrThrow().getValue(value)
|
|
|
|
|
|
obj.put(f.jsonName, writeValue(raw, options, depth + 1))
|
|
|
|
|
|
}
|
|
|
|
|
|
obj
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// 反射迭代集合:优先 toArray 转数组再 get(index);无 toArray(如 Array)直接用原集合
|
|
|
|
|
|
private static func forEachElement(collection: Any, action: (Any) -> Unit): Unit {
|
|
|
|
|
|
let ti = TypeInfo.of(collection)
|
|
|
|
|
|
var arr: Any = collection
|
|
|
|
|
|
try {
|
|
|
|
|
|
arr = ti.getInstanceFunction("toArray", []).apply(collection, [])
|
|
|
|
|
|
} catch (_: Exception) {
|
|
|
|
|
|
// 无 toArray(如 Array):直接用原集合 get(i)
|
|
|
|
|
|
}
|
|
|
|
|
|
let arrTi = TypeInfo.of(arr)
|
|
|
|
|
|
// 仓颉集合 get(index) 返回 Option<T>:Some(元素) / None(越界结束)
|
|
|
|
|
|
let getFunc = arrTi.getInstanceFunction("get", [TypeInfo.of<Int64>()])
|
|
|
|
|
|
var i: Int64 = 0
|
|
|
|
|
|
var guard: Int64 = 0
|
|
|
|
|
|
while (true) {
|
|
|
|
|
|
guard += 1
|
|
|
|
|
|
if (guard > 1000000) {
|
|
|
|
|
|
throw Exception("JsonSerializer: 集合迭代超限 type=${TypeInfo.of(arr)}")
|
|
|
|
|
|
}
|
|
|
|
|
|
var elem: ?Any = None
|
|
|
|
|
|
try {
|
|
|
|
|
|
elem = Some(getFunc.apply(arr, [i]))
|
|
|
|
|
|
} catch (_: Exception) {
|
|
|
|
|
|
break
|
|
|
|
|
|
}
|
|
|
|
|
|
if (let Some(v) <- unwrapOptionValue(elem.getOrThrow())) {
|
|
|
|
|
|
action(v)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
break
|
|
|
|
|
|
}
|
|
|
|
|
|
i += 1
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// 若值为 Option 的 Some(x) 返回 Some(x);None 或非 Option 返回 None
|
|
|
|
|
|
private static func unwrapOptionValue(v: Any): ?Any {
|
|
|
|
|
|
if (let et: EnumTypeInfo <- TypeInfo.of(v)) {
|
|
|
|
|
|
let (ctor, values) = et.destruct(v)
|
|
|
|
|
|
if (ctor.name == "Some" && values.size > 0) {
|
|
|
|
|
|
return Some(values[0])
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
None
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private static func toKeyString(k: Any): String {
|
|
|
|
|
|
if (let s: String <- k) {
|
|
|
|
|
|
return s
|
|
|
|
|
|
}
|
|
|
|
|
|
if (let s: ToString <- k) {
|
|
|
|
|
|
return s.toString()
|
|
|
|
|
|
}
|
|
|
|
|
|
TypeInfo.of(k).toString()
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// 从 "Array<String>" / "std.collection.HashMap<String, Any>" / "Option<Int64>" 提取类型参数
|
|
|
|
|
|
public static func extractTypeArgs(typeName: String): ArrayList<String> {
|
|
|
|
|
|
var args = ArrayList<String>()
|
|
|
|
|
|
match (typeName.indexOf("<")) {
|
|
|
|
|
|
case None => return args
|
|
|
|
|
|
case Some(i) =>
|
|
|
|
|
|
var depth: Int64 = 0
|
|
|
|
|
|
var start = i + 1
|
|
|
|
|
|
var j = i + 1
|
|
|
|
|
|
while (j < typeName.size) {
|
|
|
|
|
|
let b = typeName[j]
|
|
|
|
|
|
if (b == 0x3Cu8) { // '<'
|
|
|
|
|
|
depth += 1
|
|
|
|
|
|
} else if (b == 0x3Eu8) { // '>'
|
|
|
|
|
|
if (depth == 0) {
|
|
|
|
|
|
args.add(typeName[start..j])
|
|
|
|
|
|
return args
|
|
|
|
|
|
}
|
|
|
|
|
|
depth -= 1
|
|
|
|
|
|
} else if (b == 0x2Cu8) { // ','
|
|
|
|
|
|
if (depth == 0) {
|
|
|
|
|
|
args.add(typeName[start..j])
|
|
|
|
|
|
start = j + 1
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
j += 1
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
args
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|