| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071 |
- using System;
- using System.Collections;
- using Newtonsoft.Json;
- namespace Aivfo.OperationLog
- {
- /// <summary>
- /// 安全序列化 input/output(14§7 序列化兜底):
- /// - 全程 try,绝不抛异常拖垮业务;
- /// - 循环引用忽略;
- /// - 大对象 / 字节数组 / 流 只记类型名+长度,不记内容。
- /// </summary>
- 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("\"", "\\\"");
- }
- }
- }
|