using System; using System.Collections.Generic; using System.IO; using System.Linq; using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace Lskj.AgentBridge { public static class BridgeRequestParser { private static readonly ISet AllowedProperties = new HashSet(new[] { "protocolVersion", "requestId", "correlationId", "clientSessionId", "sessionScopeToken", "method", "payload", "uatGrant" }, StringComparer.Ordinal); public static BridgeRequest Parse(string json) { if (string.IsNullOrWhiteSpace(json)) throw new JsonSerializationException("桥请求 JSON 不能为空。"); JObject root; using (StringReader text = new StringReader(json)) using (StrictJsonTextReader reader = new StrictJsonTextReader(text)) { root = JObject.Load(reader, new JsonLoadSettings { CommentHandling = CommentHandling.Ignore, LineInfoHandling = LineInfoHandling.Ignore, DuplicatePropertyNameHandling = DuplicatePropertyNameHandling.Error }); if (reader.Read()) throw new JsonSerializationException("桥请求包含多个 JSON 根值。"); } foreach (JProperty property in root.Properties()) { if (!AllowedProperties.Contains(property.Name)) throw new JsonSerializationException( "桥请求包含未知字段:" + property.Name); } RequireStringWhenPresent(root, "protocolVersion"); RequireStringWhenPresent(root, "requestId"); RequireStringWhenPresent(root, "correlationId"); RequireStringWhenPresent(root, "clientSessionId"); RequireStringWhenPresent(root, "sessionScopeToken"); RequireStringWhenPresent(root, "method"); JToken payload = root["payload"]; if (payload != null && payload.Type != JTokenType.Object) throw new JsonSerializationException("桥请求 payload 必须是 JSON 对象。"); JToken uatGrant = root["uatGrant"]; if (uatGrant != null) { JObject grant = uatGrant as JObject; if (grant == null) throw new JsonSerializationException( "桥请求 uatGrant 必须是 JSON 对象。"); ISet grantFields = new HashSet( new[] { "authorizationId", "caseCode", "token" }, StringComparer.Ordinal); foreach (JProperty property in grant.Properties()) { if (!grantFields.Contains(property.Name)) throw new JsonSerializationException( "桥请求 uatGrant 包含未知字段:" + property.Name); } if (grant.Properties().Count() != 3) throw new JsonSerializationException( "桥请求 uatGrant 必须完整包含三个字段。"); RequireStringWhenPresent(grant, "authorizationId"); RequireStringWhenPresent(grant, "caseCode"); RequireStringWhenPresent(grant, "token"); } BridgeRequest request = root.ToObject(); if (request == null) throw new JsonSerializationException("桥请求无法反序列化。"); return request; } private static void RequireStringWhenPresent(JObject root, string name) { JToken value = root[name]; if (value != null && value.Type != JTokenType.String) throw new JsonSerializationException( "桥请求字段必须是字符串:" + name); } private sealed class StrictJsonTextReader : JsonTextReader { public StrictJsonTextReader(TextReader reader) : base(reader) { DateParseHandling = DateParseHandling.None; FloatParseHandling = FloatParseHandling.Decimal; MaxDepth = 64; SupportMultipleContent = false; } public override bool Read() { bool available = base.Read(); if (available && TokenType == JsonToken.Comment) throw new JsonReaderException("桥请求不允许 JSON 注释。"); return available; } } } }