using System; using System.Collections; using Newtonsoft.Json; namespace Aivfo.OperationLog { /// /// 安全序列化 input/output(14§7 序列化兜底): /// - 全程 try,绝不抛异常拖垮业务; /// - 循环引用忽略; /// - 大对象 / 字节数组 / 流 只记类型名+长度,不记内容。 /// internal static class SafeSerializer { private static readonly JsonSerializerSettings Settings = new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore, NullValueHandling = NullValueHandling.Ignore, MaxDepth = 8 }; // 超过此长度的字符串只保留摘要,避免大对象冲垮日志。 private const int MaxJsonLength = 4000; public static string Serialize(object value) { if (value == null) return null; try { // 字符串直接用(但截断)。 if (value is string s) return Cap(s); // 大对象 / 二进制:只记类型名 + 长度,不记内容。 if (value is byte[] bytes) return $"{{\"_type\":\"byte[]\",\"length\":{bytes.Length}}}"; if (value is System.IO.Stream stream) return $"{{\"_type\":\"Stream\",\"canRead\":{stream.CanRead.ToString().ToLowerInvariant()}}}"; var json = JsonConvert.SerializeObject(value, Settings); return Cap(json); } catch (Exception ex) { // 序列化失败:退而记类型名 + 异常,绝不抛出。 try { var typeName = value.GetType().FullName; if (value is ICollection col) return $"{{\"_type\":\"{typeName}\",\"count\":{col.Count},\"_serErr\":\"{Escape(ex.Message)}\"}}"; return $"{{\"_type\":\"{typeName}\",\"_serErr\":\"{Escape(ex.Message)}\"}}"; } catch { return "{\"_serErr\":\"unserializable\"}"; } } } private static string Cap(string json) { if (string.IsNullOrEmpty(json) || json.Length <= MaxJsonLength) return json; return json.Substring(0, MaxJsonLength) + $"...(truncated,len={json.Length})"; } private static string Escape(string s) { return (s ?? string.Empty).Replace("\\", "\\\\").Replace("\"", "\\\""); } } }