101 lines
2.9 KiB
Plaintext
101 lines
2.9 KiB
Plaintext
/*
|
||||
|
|
* Copyright (c) 2025 SimcuTeam. All rights reserved.
|
|||
|
|
* 移植自 C# 项目 SimApi(E:\simcu\simapi-net),遵循 MIT 许可证。
|
|||
|
|
* JSON 序列化统一工具(对应 C# SimApiUtil.Json)。
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
package simapi.communications
|
|||
|
|
|
|||
|
|
import std.collection.*
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* JSON 序列化静态工具类。
|
|||
|
|
*
|
|||
|
|
* 说明:序列化核心放在依赖图最底层的 simapi.communications 包,
|
|||
|
|
* SimApiUtil.json(simapi.helpers)委托本类实现,避免循环依赖;
|
|||
|
|
* 全框架 JSON 输出统一走此处,保证转义与格式一致。
|
|||
|
|
*/
|
|||
|
|
public class SimApiJson {
|
|||
|
|
private init() {}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 对象序列化为 JSON 字符串(统一入口)。
|
|||
|
|
* 支持 String/Int64/Bool/Float64/Array/HashMap,其他类型退化为字符串。
|
|||
|
|
* @param obj 任意对象(None 输出 null)。
|
|||
|
|
*/
|
|||
|
|
public static func json(obj: ?Any): String {
|
|||
|
|
if (let Some(obj) <- obj) {
|
|||
|
|
return jsonValue(obj)
|
|||
|
|
}
|
|||
|
|
"null"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* JSON 字符串转义(统一入口)。
|
|||
|
|
* @param s 原始字符串。
|
|||
|
|
* @return 转义后可直接放入 JSON 字符串字面量的内容。
|
|||
|
|
*/
|
|||
|
|
public static func escapeJson(s: String): String {
|
|||
|
|
var sb = StringBuilder()
|
|||
|
|
for (c in s.runes()) {
|
|||
|
|
match (c) {
|
|||
|
|
case '"' => sb.append("\\\"")
|
|||
|
|
case '\\' => sb.append("\\\\")
|
|||
|
|
case '\n' => sb.append("\\n")
|
|||
|
|
case '\r' => sb.append("\\r")
|
|||
|
|
case '\t' => sb.append("\\t")
|
|||
|
|
case _ => sb.append(c)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
sb.toString()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private static func jsonValue(obj: Any): String {
|
|||
|
|
if (let s: String <- obj) {
|
|||
|
|
return "\"${escapeJson(s)}\""
|
|||
|
|
}
|
|||
|
|
if (let i: Int64 <- obj) {
|
|||
|
|
return "${i}"
|
|||
|
|
}
|
|||
|
|
if (let b: Bool <- obj) {
|
|||
|
|
return "${b}"
|
|||
|
|
}
|
|||
|
|
if (let f: Float64 <- obj) {
|
|||
|
|
return "${f}"
|
|||
|
|
}
|
|||
|
|
if (let arr: Array<Any> <- obj) {
|
|||
|
|
var sb = StringBuilder()
|
|||
|
|
sb.append("[")
|
|||
|
|
var first = true
|
|||
|
|
for (item in arr) {
|
|||
|
|
if (!first) { sb.append(",") }
|
|||
|
|
sb.append(jsonValue(item))
|
|||
|
|
first = false
|
|||
|
|
}
|
|||
|
|
sb.append("]")
|
|||
|
|
return sb.toString()
|
|||
|
|
}
|
|||
|
|
if (let map: HashMap<String, Any> <- obj) {
|
|||
|
|
var sb = StringBuilder()
|
|||
|
|
sb.append("{")
|
|||
|
|
var first = true
|
|||
|
|
for ((key, value) in map) {
|
|||
|
|
if (!first) { sb.append(",") }
|
|||
|
|
sb.append("\"${escapeJson(key)}\":${jsonValue(value)}")
|
|||
|
|
first = false
|
|||
|
|
}
|
|||
|
|
sb.append("}")
|
|||
|
|
return sb.toString()
|
|||
|
|
}
|
|||
|
|
// 其他类型退化为字符串
|
|||
|
|
return "\"${escapeJson(describe(obj))}\""
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private static func describe(obj: Any): String {
|
|||
|
|
if (let s: ToString <- obj) {
|
|||
|
|
return s.toString()
|
|||
|
|
}
|
|||
|
|
"null"
|
|||
|
|
}
|
|||
|
|
}
|