Files
simapi-cj/src/communications/SimApiJson.cj
T

101 lines
2.9 KiB
Plaintext
Raw Normal View History

2026-08-16 12:46:15 +08:00
/*
* Copyright (c) 2025 SimcuTeam. All rights reserved.
* 移植自 C# 项目 SimApiE:\simcu\simapi-net),遵循 MIT 许可证。
* JSON 序列化统一工具(对应 C# SimApiUtil.Json)。
*/
package simapi.communications
import std.collection.*
/**
* JSON 序列化静态工具类。
*
* 说明:序列化核心放在依赖图最底层的 simapi.communications 包,
* SimApiUtil.jsonsimapi.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"
}
}