diff --git a/cjpm.lock b/cjpm.lock index cff007f..7b775eb 100644 --- a/cjpm.lock +++ b/cjpm.lock @@ -2,19 +2,19 @@ version = 0 [requires] soulsoft_extensions_hosting = {version = "1.0.20260528"} - soulsoft_web_http = {version = "1.0.20260528"} - soulsoft_web_hosting = {version = "1.0.20260528"} - soulsoft_extensions_logging = {version = "1.0.20260528"} + soulsoft_web_cors = {version = "1.0.20260528"} soulsoft_extensions_options_configuration = {version = "1.0.20260528"} + soulsoft_web_http = {version = "1.0.20260528"} + soulsoft_extensions_logging = {version = "1.0.20260528"} + soulsoft_extensions_configuration = {version = "1.0.20260528"} soulsoft_web_routing = {version = "1.0.20260528"} soulsoft_extensions_logging_console = {version = "1.0.20260528"} - soulsoft_serialization = {version = "1.0.20260528"} - soulsoft_net_http = {version = "1.0.20260528"} - soulsoft_web_mvc = {version = "1.0.20260528"} + soulsoft_extensions_injection = {version = "1.0.20260528"} + redis = {version = "1.0.20260627"} + soulsoft_web_hosting = {version = "1.0.20260528"} soulsoft_extensions_logging_configuration = {version = "1.0.20260528"} soulsoft_identity_claims = {version = "1.0.20260528"} - soulsoft_extensions_configuration = {version = "1.0.20260528"} + soulsoft_web_mvc = {version = "1.0.20260528"} + soulsoft_serialization = {version = "1.0.20260528"} soulsoft_extensions_options = {version = "1.0.20260528"} - soulsoft_web_cors = {version = "1.0.20260528"} - redis = {version = "1.0.20260627"} - soulsoft_extensions_injection = {version = "1.0.20260528"} + soulsoft_net_http = {version = "1.0.20260528"} diff --git a/src/authsdk/SimApiAuthCenter.cj b/src/authsdk/SimApiAuthCenter.cj index 26301e1..e9cf833 100644 --- a/src/authsdk/SimApiAuthCenter.cj +++ b/src/authsdk/SimApiAuthCenter.cj @@ -65,7 +65,7 @@ public class SimApiAuthCenter { response.ensureSuccessStatusCode() let json = response.content.readAsString() let resp = JsonSerializer.Deserialize(json) - SimApiError.errorWhen(resp._code != 200, code: 400, message: "签名验证失败") + SimApiError.errorWhen(resp.code != 200, code: 400, message: "签名验证失败") } finally { response.close() } @@ -92,7 +92,7 @@ public class SimApiAuthCenter { body["keyword"] = keyword body["skip"] = skip body["take"] = take - _client.signQuery>("/api/auth/group/search", body: SimApiJson.json(Some(body))) + _client.signQuery>("/api/auth/group/search", body: SimApiUtil.json(Some(body))) } /** @@ -102,7 +102,7 @@ public class SimApiAuthCenter { var body = HashMap() body["profileId"] = profileId body["groupId"] = groupId - _client.signQuery("/api/auth/group/detail", body: SimApiJson.json(Some(body))) + _client.signQuery("/api/auth/group/detail", body: SimApiUtil.json(Some(body))) } /** @@ -113,7 +113,7 @@ public class SimApiAuthCenter { body["groupId"] = groupId body["profileId"] = profileId _client.signQuery>("/api/auth/internal/group/related-group-ids", - body: SimApiJson.json(Some(body))) + body: SimApiUtil.json(Some(body))) } // ===== Profile 相关 ===== @@ -126,7 +126,7 @@ public class SimApiAuthCenter { body["keyword"] = keyword body["skip"] = skip body["take"] = take - _client.signQuery>("/api/auth/profile/search", body: SimApiJson.json(Some(body))) + _client.signQuery>("/api/auth/profile/search", body: SimApiUtil.json(Some(body))) } /** @@ -139,7 +139,7 @@ public class SimApiAuthCenter { arr.add(id) } body["ids"] = arr.toArray() - _client.signQuery>("/api/auth/profile/list", body: SimApiJson.json(Some(body))) + _client.signQuery>("/api/auth/profile/list", body: SimApiUtil.json(Some(body))) } // ===== AuthGate 内部应用专用 ===== @@ -151,7 +151,7 @@ public class SimApiAuthCenter { var body = HashMap() body["ProfileId"] = profileId body["AppId"] = applicationId - _client.signQuery("/api/auth/internal/app/check-owner", body: SimApiJson.json(Some(body))) + _client.signQuery("/api/auth/internal/app/check-owner", body: SimApiUtil.json(Some(body))) } /** @@ -166,7 +166,7 @@ public class SimApiAuthCenter { } body["AllowedAppIds"] = arr.toArray() _client.signQuery>("/api/auth/internal/app/related", - body: SimApiJson.json(Some(body))) + body: SimApiUtil.json(Some(body))) } // ===== 系统登录 ===== @@ -184,7 +184,7 @@ public class SimApiAuthCenter { if (let Some(scene) <- scene) { body["scene"] = scene } if (let Some(data) <- data) { body["data"] = data } if (let Some(backUrl) <- backUrl) { body["backUrl"] = backUrl } - let code = _client.signQuery("/api/auth/login/code", body: SimApiJson.json(Some(body))) + let code = _client.signQuery("/api/auth/login/code", body: SimApiUtil.json(Some(body))) let server = _client.server GetCodeResponse(code, server, "${server}/auth?code=${code}") } @@ -195,10 +195,10 @@ public class SimApiAuthCenter { public func getLoginInfo(code: String, scene!: ?String = None): LoginInfoResponse { var body = HashMap() body["code"] = code - // 说明:C# 的 ErrorWhenNull(resp, 400232, "登录信息获取失败") 对应 signQuery 内部 _data.getOrThrow() 的 + // 说明:C# 的 ErrorWhenNull(resp, 400232, "登录信息获取失败") 对应 signQuery 内部 data.getOrThrow() 的 // None 分支;仓颉版 signQuery 返回非空 T(data 缺失即抛异常),故此处无需重复判空。 - let resp = _client.signQuery("/api/auth/login/get", body: SimApiJson.json(Some(body))) - SimApiError.errorWhen(resp._scene != scene, code: 403003, message: "登录场景不匹配") + let resp = _client.signQuery("/api/auth/login/get", body: SimApiUtil.json(Some(body))) + SimApiError.errorWhen(resp.scene != scene, code: 403003, message: "登录场景不匹配") resp } @@ -214,7 +214,7 @@ public class SimApiAuthCenter { if (let Some(data) <- data) { body["data"] = data } if (let Some(backUrl) <- backUrl) { body["backUrl"] = backUrl } body["profileId"] = userId - let code = _client.signQuery("/api/auth/confirm/code", body: SimApiJson.json(Some(body))) + let code = _client.signQuery("/api/auth/confirm/code", body: SimApiUtil.json(Some(body))) let server = _client.server GetCodeResponse(code, server, "${server}/confirm?code=${code}") } @@ -225,14 +225,14 @@ public class SimApiAuthCenter { public func confirm(code: String, scene: String, userId!: ?String = None): ConfirmResponse { var body = HashMap() body["code"] = code - let resp = _client.signQuery("/api/auth/confirm/get", body: SimApiJson.json(Some(body))) - SimApiError.errorWhen(userId != Some(resp._profileId), code: 403002, message: "安全确认身份不匹配") - SimApiError.errorWhen(resp._scene != scene, code: 403003, message: "安全确认场景不匹配") + let resp = _client.signQuery("/api/auth/confirm/get", body: SimApiUtil.json(Some(body))) + SimApiError.errorWhen(userId != Some(resp.profileId), code: 403002, message: "安全确认身份不匹配") + SimApiError.errorWhen(resp.scene != scene, code: 403003, message: "安全确认场景不匹配") resp } /// 简单单字段请求体:{"field":"value"} private static func simpleBody(field: String, value: String): String { - "{\"${field}\":\"${SimApiJson.escapeJson(value)}\"}" + "{\"${field}\":\"${SimApiUtil.escapeJson(value)}\"}" } } diff --git a/src/authsdk/SimApiAuthDto.cj b/src/authsdk/SimApiAuthDto.cj index 349f25b..dfa2252 100644 --- a/src/authsdk/SimApiAuthDto.cj +++ b/src/authsdk/SimApiAuthDto.cj @@ -18,49 +18,49 @@ import std.collection.* * 应用/Profile 通用项(对齐 C# AppAndProfileItem)。 */ public class AppAndProfileItem { - public var _id: String = "" - public var _name: String = "" - public var _image: ?String = None - public var _description: ?String = None + public var id: String = "" + public var name: String = "" + public var image: ?String = None + public var description: ?String = None } /** * 安全确认响应(对齐 C# ConfirmResponse)。 - * _data 用 ?HashMap 对齐 C# Dictionary?(任意 JSON 对象)。 + * data 用 ?HashMap 对齐 C# Dictionary?(任意 JSON 对象)。 */ public class ConfirmResponse { - public var _applicationId: String = "" - public var _profileId: String = "" - public var _scene: ?String = None - public var _data: ?HashMap = None + public var applicationId: String = "" + public var profileId: String = "" + public var scene: ?String = None + public var data: ?HashMap = None } /** * 登录信息响应(对齐 C# LoginInfoResponse)。 */ public class LoginInfoResponse { - public var _scene: ?String = None - public var _data: ?HashMap = None - public var _profileId: String = "" - public var _name: String = "" - public var _image: ?String = None - public var _description: ?String = None + public var scene: ?String = None + public var data: ?HashMap = None + public var profileId: String = "" + public var name: String = "" + public var image: ?String = None + public var description: ?String = None } /** * 获取授权码响应(对齐 C# GetCodeResponse)。 */ public class GetCodeResponse { - public var _code: String = "" - public var _server: String = "" - public var _fullUrl: String = "" + public var code: String = "" + public var server: String = "" + public var fullUrl: String = "" public init() {} public init(code: String, server: String, fullUrl: String) { - this._code = code - this._server = server - this._fullUrl = fullUrl + this.code = code + this.server = server + this.fullUrl = fullUrl } } @@ -68,42 +68,42 @@ public class GetCodeResponse { * 群组关联项(对齐 C# GroupRelatedItem)。 */ public class GroupRelatedItem { - public var _id: String = "" - public var _name: String = "" - public var _image: ?String = None - public var _description: ?String = None - public var _isOwner: Bool = false - public var _isAdmin: Bool = false - public var _isMember: Bool = false + public var id: String = "" + public var name: String = "" + public var image: ?String = None + public var description: ?String = None + public var isOwner: Bool = false + public var isAdmin: Bool = false + public var isMember: Bool = false } /** * 群组详情树节点(对齐 C# GroupDetailTreeNode,children 递归)。 */ public class GroupDetailTreeNode { - public var _id: String = "" - public var _name: String = "" - public var _image: ?String = None - public var _description: ?String = None - public var _sort: Int64 = 0 - public var _children: Array = [] + public var id: String = "" + public var name: String = "" + public var image: ?String = None + public var description: ?String = None + public var sort: Int64 = 0 + public var children: Array = [] } /** * 权限项(对齐 C# PermissionItem)。 */ public class PermissionItem { - public var _identifier: String = "" - public var _name: String = "" - public var _group: String = "" - public var _description: String = "" + public var identifier: String = "" + public var name: String = "" + public var group: String = "" + public var description: String = "" public init() {} public init(identifier: String, name: String, group: String, description: String) { - this._identifier = identifier - this._name = name - this._group = group - this._description = description + this.identifier = identifier + this.name = name + this.group = group + this.description = description } } diff --git a/src/authsdk/SimApiAuthIam.cj b/src/authsdk/SimApiAuthIam.cj index 6e13acb..94ba679 100644 --- a/src/authsdk/SimApiAuthIam.cj +++ b/src/authsdk/SimApiAuthIam.cj @@ -29,15 +29,15 @@ public class SimApiAuthIam { var items = ArrayList() for (p in permissions) { var item = HashMap() - item["identifier"] = p._identifier - item["name"] = p._name - item["group"] = p._group - item["description"] = p._description + item["identifier"] = p.identifier + item["name"] = p.name + item["group"] = p.group + item["description"] = p.description items.add(item) } var body = HashMap() body["permissions"] = items.toArray() - _client.signQuery("/api/iam/permission/register", body: SimApiJson.json(Some(body))) + _client.signQuery("/api/iam/permission/register", body: SimApiUtil.json(Some(body))) } /** @@ -49,7 +49,7 @@ public class SimApiAuthIam { if (let Some(groupId) <- groupId) { body["groupId"] = groupId } - _client.signQuery>("/api/iam/permission/owned", body: SimApiJson.json(Some(body))) + _client.signQuery>("/api/iam/permission/owned", body: SimApiUtil.json(Some(body))) } /** @@ -62,7 +62,7 @@ public class SimApiAuthIam { if (let Some(groupId) <- groupId) { body["groupId"] = groupId } - let ok = _client.signQuery("/api/iam/permission/check", body: SimApiJson.json(Some(body))) + let ok = _client.signQuery("/api/iam/permission/check", body: SimApiUtil.json(Some(body))) SimApiError.errorWhen(!ok, code: 403, message: "没有该权限") } } diff --git a/src/communications/SimApiBaseResponse.cj b/src/communications/SimApiBaseResponse.cj index 393e3c9..87389c7 100644 --- a/src/communications/SimApiBaseResponse.cj +++ b/src/communications/SimApiBaseResponse.cj @@ -6,33 +6,29 @@ package simapi.communications import std.collection.* -import simapi_serialization.* -import simapi_serialization.macros.* /** * 基础响应体:所有接口统一返回该结构。 * HTTP 状态码始终 200,业务错误通过 code 字段表达。 - * 序列化/反序列化由 simapi_serialization 反射处理(无需接口/宏); - * @SerializerParent 使子类(SimApiResponse/SimApiDataResponse)序列化时包含 _code/_message。 + * 序列化/反序列化由 simapi_serialization 反射处理(无需接口/宏)。 */ -@SerializerParent -public open class SimApiBaseResponse { - public var _code: Int64 = 200 - public var _message: String = "成功" +public class SimApiBaseResponse { + public var code: Int64 = 200 + public var message: String = "成功" public init(code: Int64, message: String) { - this._code = code - this._message = message + this.code = code + this.message = message } public init(code: Int64) { - this._code = code - this._message = getDefaultMessage(code) + this.code = code + this.message = getDefaultMessage(code) } public init() { - this._code = 200 - this._message = "成功" + this.code = 200 + this.message = "成功" } /** @@ -50,20 +46,6 @@ public open class SimApiBaseResponse { case _ => "未知错误代码" } } - - /** - * 序列化为 JSON 字符串(可选 data 字段)。 - * @param dataJson 已序列化的 data JSON 字符串(可选)。 - */ - public func toJsonString(dataJson!: String = ""): String { - var sb = StringBuilder() - sb.append("{\"code\":${_code},\"message\":\"${SimApiJson.escapeJson(_message)}\"") - if (!dataJson.isEmpty()) { - sb.append(",\"data\":${dataJson}") - } - sb.append("}") - sb.toString() - } } /** @@ -72,18 +54,18 @@ public open class SimApiBaseResponse { * 说明:泛型类暂不通过反射序列化,可手动转换为 SimApiResponse。 */ public class PageResponse { - public var _list: Array = Array() - public var _page: Int64 = 1 - public var _count: Int64 = 20 - public var _total: Int64 = 0 + public var list: Array = Array() + public var page: Int64 = 1 + public var count: Int64 = 20 + public var total: Int64 = 0 public init() {} public init(list: Array, page: Int64, count: Int64, total: Int64) { - this._list = list - this._page = page - this._count = count - this._total = total + this.list = list + this.page = page + this.count = count + this.total = total } } @@ -91,28 +73,29 @@ public class PageResponse { * 带数据的动态响应。 * @param T 数据类型。 * 序列化/反序列化由 simapi_serialization 反射处理: - * - data 为对象/数组/标量,反射递归 + * - code/message/data 为普通字段,反射递归 * - data 支持任意 T(免约束) * 注:泛型嵌套(SimApiResponse)的反射反序列化已验证可用。 */ -public class SimApiResponse <: SimApiBaseResponse { - public var _data: ?T = None +public class SimApiResponse { + public var code: Int64 = 200 + public var message: String = "成功" + public var data: ?T = None - public init() { - super() - } + public init() {} public init(data: T) { - super() - this._data = Some(data) + this.data = Some(data) } public init(code: Int64, message: String) { - super(code, message) + this.code = code + this.message = message } public init(code: Int64, message: String, data: T) { - super(code, message) - this._data = Some(data) + this.code = code + this.message = message + this.data = Some(data) } } diff --git a/src/communications/SimApiDataResponse.cj b/src/communications/SimApiDataResponse.cj index 3f1f7b2..13e0707 100644 --- a/src/communications/SimApiDataResponse.cj +++ b/src/communications/SimApiDataResponse.cj @@ -12,27 +12,28 @@ package simapi.communications * SimApiRequestDelegateFactory 派发结果时统一包装 DTO/数组/动态结构。 * * 序列化/反序列化由 simapi_serialization 反射处理: - * - data 为对象/数组/标量,反射递归 + * - code/message/data 为普通字段,反射递归 * - data 为动态结构(HashMap)同样反射支持 */ -public class SimApiDataResponse <: SimApiBaseResponse { - public var _data: ?Any = None +public class SimApiDataResponse { + public var code: Int64 = 200 + public var message: String = "成功" + public var data: ?Any = None - public init() { - super() - } + public init() {} public init(data: Any) { - super() - this._data = Some(data) + this.data = Some(data) } public init(code: Int64, message: String) { - super(code, message) + this.code = code + this.message = message } public init(code: Int64, message: String, data: Any) { - super(code, message) - this._data = Some(data) + this.code = code + this.message = message + this.data = Some(data) } } diff --git a/src/communications/SimApiJson.cj b/src/communications/SimApiJson.cj deleted file mode 100644 index 6ac4d7a..0000000 --- a/src/communications/SimApiJson.cj +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2025 SimcuTeam. All rights reserved. - * 移植自 C# 项目 SimApi(E:\simcu\simapi-net),遵循 MIT 许可证。 - * JSON 序列化统一工具(对应 C# SimApiUtil.Json)。 - */ - -package simapi.communications - -import std.collection.* -import simapi_serialization.* - -/** - * JSON 序列化静态工具类。 - * - * 说明:序列化核心委托给 simapi_serialization(JsonSerializer.Serialize), - * 全框架 JSON 输出统一走此处,保证与序列化库行为一致。 - */ -public class SimApiJson { - private init() {} - - /** - * 对象序列化为 JSON 字符串(统一入口)。 - * @param obj 任意对象(None 输出 null)。 - */ - public static func json(obj: ?Any): String { - if (let Some(obj) <- obj) { - return JsonSerializer.Serialize(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() - } -} diff --git a/src/communications/SimApiLoginItem.cj b/src/communications/SimApiLoginItem.cj index 873a263..88f487e 100644 --- a/src/communications/SimApiLoginItem.cj +++ b/src/communications/SimApiLoginItem.cj @@ -13,27 +13,27 @@ import std.collection.* * 对齐 C# SimApiLoginItem(Id / Type / Meta / Extra)。 * * 序列化/反序列化由 simapi_serialization 反射处理(免标注、免约束), - * 字段 _id/_types/_meta/_extra 全部为受支持类型(String/Array/HashMap)。 + * 字段 id/types/meta/extra 全部为受支持类型(String/Array/HashMap)。 */ public class SimApiLoginItem { - public var _id: String = "" - public var _types: Array = ["user"] - public var _meta: HashMap = HashMap() - public var _extra: HashMap = HashMap() + public var id: String = "" + public var types: Array = ["user"] + public var meta: HashMap = HashMap() + public var extra: HashMap = HashMap() public init() {} public init(id: String) { - this._id = id - this._types = ["user"] - this._meta = HashMap() - this._extra = HashMap() + this.id = id + this.types = ["user"] + this.meta = HashMap() + this.extra = HashMap() } public init(id: String, types: Array) { - this._id = id - this._types = types - this._meta = HashMap() - this._extra = HashMap() + this.id = id + this.types = types + this.meta = HashMap() + this.extra = HashMap() } } diff --git a/src/helpers/SimApiAesBodyChecker.cj b/src/helpers/SimApiAesBodyChecker.cj index 6aa1611..c7862e5 100644 --- a/src/helpers/SimApiAesBodyChecker.cj +++ b/src/helpers/SimApiAesBodyChecker.cj @@ -17,7 +17,7 @@ import simapi.interfaces.* * AES body 请求({"data": "密文"},对齐 C# SimApiOneFieldRequest)。 */ public class AesBodyRequest { - public var _data: String = "" + public var data: String = "" } /** @@ -54,7 +54,7 @@ public class SimApiAesBodyChecker { // 2. 反序列化 {"data": "密文"} let req = JsonSerializer.Deserialize(body) - if (req._data.isEmpty()) { + if (req.data.isEmpty()) { SimApiError.error(code: 400, message: "请求体缺少密文Data字段") } @@ -76,7 +76,7 @@ public class SimApiAesBodyChecker { } // 5. 解密 - let jsonStr = SimApiAesUtil.decrypt(req._data, key.getOrThrow()) + let jsonStr = SimApiAesUtil.decrypt(req.data, key.getOrThrow()) if (jsonStr.isEmpty()) { SimApiError.error(code: 400, message: "解密失败") } diff --git a/src/helpers/SimApiAuth.cj b/src/helpers/SimApiAuth.cj index dc0aee7..c546b1d 100644 --- a/src/helpers/SimApiAuth.cj +++ b/src/helpers/SimApiAuth.cj @@ -84,7 +84,7 @@ public class SimApiAuth { public func login(loginItem: SimApiLoginItem, expireSeconds!: Int64 = 604800, token!: String = ""): String { let newToken = if (token.isEmpty()) { generateToken() } else { token } let tokenKey = "${tokenCachePrefix}${newToken}" - let setKey = "${tokenSetCachePrefix}${loginItem._id}" + let setKey = "${tokenSetCachePrefix}${loginItem.id}" let json = loginItemJson(loginItem) if (let Some(redis) <- _redis) { @@ -93,10 +93,10 @@ public class SimApiAuth { redis.expire(setKey, expireSeconds) } else { _tokenStore[newToken] = TokenEntry(json, nowMillis() + expireSeconds * 1000) - var tokens = _userTokens.get(loginItem._id) + var tokens = _userTokens.get(loginItem.id) if (tokens == None) { tokens = HashSet() - _userTokens[loginItem._id] = tokens.getOrThrow() + _userTokens[loginItem.id] = tokens.getOrThrow() } tokens.getOrThrow().add(newToken) } @@ -187,7 +187,7 @@ public class SimApiAuth { public func logout(token: String): Unit { let item = getLogin(token) if (let Some(item) <- item) { - removeTokenOfUser(item._id, token) + removeTokenOfUser(item.id, token) } let tokenKey = "${tokenCachePrefix}${token}" if (let Some(redis) <- _redis) { diff --git a/src/helpers/SimApiHttpClient.cj b/src/helpers/SimApiHttpClient.cj index 5126a25..b759047 100644 --- a/src/helpers/SimApiHttpClient.cj +++ b/src/helpers/SimApiHttpClient.cj @@ -131,8 +131,8 @@ public open class SimApiHttpClient { SimApiError.errorWhenFalse(response.isSuccessStatusCode, code: response.statusCode, message: "HTTP ERROR: ${response.statusCode}") let json = response.content.readAsString() let result = JsonSerializer.Deserialize>(json) - SimApiError.errorWhen(result._code != 200, code: result._code, message: result._message) - return result._data.getOrThrow() + SimApiError.errorWhen(result.code != 200, code: result.code, message: result.message) + return result.data.getOrThrow() } finally { response.close() } diff --git a/src/helpers/SimApiRequestDelegateFactory.cj b/src/helpers/SimApiRequestDelegateFactory.cj index e728e59..aa14d13 100644 --- a/src/helpers/SimApiRequestDelegateFactory.cj +++ b/src/helpers/SimApiRequestDelegateFactory.cj @@ -268,7 +268,7 @@ struct SimApiActionInvoker { let requiredTypes = auth.`type`.split(",") var matched = false for (t in requiredTypes) { - if (loginItem._types.contains(t)) { + if (loginItem.types.contains(t)) { matched = true break } diff --git a/src/helpers/SimApiUtil.cj b/src/helpers/SimApiUtil.cj index db1b234..712fafd 100644 --- a/src/helpers/SimApiUtil.cj +++ b/src/helpers/SimApiUtil.cj @@ -172,10 +172,34 @@ public class SimApiUtil { } /** - * 将对象序列化为 JSON 字符串(委托给 SimApiJson.json 统一实现,对齐 C# SimApiUtil.Json)。 + * 将对象序列化为 JSON 字符串(对齐 C# SimApiUtil.Json)。 + * @param obj 任意对象(None 输出 null)。 */ public static func json(obj: ?Any): String { - SimApiJson.json(obj) + if (let Some(obj) <- obj) { + return JsonSerializer.Serialize(obj) + } + "null" + } + + /** + * JSON 字符串转义(对齐 C# 内部转义逻辑)。 + * @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() } /** @@ -194,7 +218,7 @@ public class SimApiUtil { * @return Base64 字符串。 */ public static func base64Encode(obj: Any): String { - let json = SimApiJson.json(Some(obj)) + let json = json(Some(obj)) base64Encode(json) } diff --git a/src/middlewares/SimApiExceptionMiddleware.cj b/src/middlewares/SimApiExceptionMiddleware.cj index 4c2bd06..4731d58 100644 --- a/src/middlewares/SimApiExceptionMiddleware.cj +++ b/src/middlewares/SimApiExceptionMiddleware.cj @@ -61,7 +61,7 @@ public class SimApiExceptionMiddleware <: IMiddleware { } var response = SimApiBaseResponse(simEx.code, message) if (context.response.statusCode == 404) { - response._message = "接口不存在" + response.message = "接口不存在" } return response } diff --git a/src/middlewares/SimApiRequestLogMiddleware.cj b/src/middlewares/SimApiRequestLogMiddleware.cj index 3082701..db04da5 100644 --- a/src/middlewares/SimApiRequestLogMiddleware.cj +++ b/src/middlewares/SimApiRequestLogMiddleware.cj @@ -13,6 +13,7 @@ import soulsoft_extensions_logging.* import simapi_serialization.* import simapi.communications.* import simapi.configurations.* +import simapi.helpers.* /** * 请求日志中间件:记录请求方法、URL、请求头、请求体、响应状态码、耗时与异常。 @@ -93,7 +94,7 @@ public class SimApiRequestLogMiddleware <: IMiddleware { var first = true for ((name, values) in context.request.headers) { if (!first) { sb.append(",") } - sb.append("\"${SimApiJson.escapeJson(name)}\":\"${SimApiJson.escapeJson(joinValues(values))}\"") + sb.append("\"${SimApiUtil.escapeJson(name)}\":\"${SimApiUtil.escapeJson(joinValues(values))}\"") first = false } sb.append("}\n") @@ -147,15 +148,15 @@ public class SimApiRequestLogMiddleware <: IMiddleware { var first = true for ((k, v) in map) { if (!first) { sb.append(",") } - sb.append("\"${SimApiJson.escapeJson(k)}\":") + sb.append("\"${SimApiUtil.escapeJson(k)}\":") if (let s: String <- v) { if (s.size > maxLen) { - sb.append("\"${SimApiJson.escapeJson(s[0..maxLen])}...(${s.size})\"") + sb.append("\"${SimApiUtil.escapeJson(s[0..maxLen])}...(${s.size})\"") } else { - sb.append("\"${SimApiJson.escapeJson(s)}\"") + sb.append("\"${SimApiUtil.escapeJson(s)}\"") } } else { - sb.append(SimApiJson.json(Some(v))) + sb.append(SimApiUtil.json(Some(v))) } first = false }