Serilog无法解构集合内的匿名复杂对象问题求助
解决Serilog无法解构Dictionary<string, object>中复杂对象的问题
当使用Serilog日志Dictionary<string, object>类型的属性时,如果其中包含反序列化后的复杂对象(比如Newtonsoft.Json的JObject或System.Text.Json的JsonElement),Serilog默认无法正确解构,会输出类似[ [[]], [[]] ]的异常结果。以下是几种可行的解决方案:
方案1:自定义Serilog解构器
通过实现IDestructuringPolicy,让Serilog能识别并正确解构JObject或JsonElement类型。
针对Newtonsoft.Json的JObject
创建解构器类:
using Serilog.Core; using Serilog.Events; using Newtonsoft.Json.Linq; public class JObjectDestructuringPolicy : IDestructuringPolicy { public bool TryDestructure(object value, ILogEventPropertyValueFactory propertyValueFactory, out LogEventPropertyValue result) { if (value is JObject jObject) { var properties = jObject.Properties() .Select(p => new LogEventProperty(p.Name, propertyValueFactory.CreatePropertyValue(p.Value, destructureObjects: true))); result = new StructureValue(properties); return true; } result = null; return false; } }
注册到Serilog配置:
Log.Logger = new LoggerConfiguration() .Destructure.With<JObjectDestructuringPolicy>() // 其他配置(如输出目标、格式化器等) .CreateLogger();
针对System.Text.Json的JsonElement
创建解构器类:
using Serilog.Core; using Serilog.Events; using System.Text.Json; public class JsonElementDestructuringPolicy : IDestructuringPolicy { public bool TryDestructure(object value, ILogEventPropertyValueFactory propertyValueFactory, out LogEventPropertyValue result) { if (value is JsonElement element && element.ValueKind == JsonValueKind.Object) { var properties = element.EnumerateObject() .Select(p => new LogEventProperty(p.Name, propertyValueFactory.CreatePropertyValue(p.Value, destructureObjects: true))); result = new StructureValue(properties); return true; } result = null; return false; } }
注册到Serilog配置:
Log.Logger = new LoggerConfiguration() .Destructure.With<JsonElementDestructuringPolicy>() // 其他配置 .CreateLogger();
方案2:修改反序列化配置,将复杂对象转为ExpandoObject
通过调整Web API的反序列化规则,让JSON中的复杂对象直接转为ExpandoObject(Serilog原生支持解构该类型)。
使用Newtonsoft.Json
在Program.cs/Startup.cs中配置:
builder.Services.AddControllers() .AddNewtonsoftJson(options => { // 添加ExpandoObject转换器,将复杂对象转为ExpandoObject options.SerializerSettings.Converters.Add(new Newtonsoft.Json.Converters.ExpandoObjectConverter()); });
使用System.Text.Json
在Program.cs/Startup.cs中配置:
builder.Services.AddControllers() .AddJsonOptions(options => { options.JsonSerializerOptions.Converters.Add(new System.Text.Json.Serialization.JsonConverter<object>( (reader, typeToConvert, options) => JsonSerializer.Deserialize<System.Dynamic.ExpandoObject>(reader, options), (writer, value, options) => JsonSerializer.Serialize(writer, value, options) )); });
方案3:手动处理对象后再日志输出
如果只需要局部处理,可以在日志前将JObject/JsonElement转为Serilog可识别的类型:
[HttpPost("information")] public void LogInformation([FromBody] LogRequest requestData) { var processedMetaData = requestData.AdditionalMetaData?.ToDictionary( k => k.Key, v => v.Value switch { JObject jObj => jObj.ToObject<dynamic>(), JsonElement elem => JsonSerializer.Deserialize<dynamic>(elem.GetRawText()), _ => v.Value } ); var logData = new { requestData.LogMessage, AdditionalMetaData = processedMetaData }; logger.Information("{@logData}", logData); }
内容的提问来源于stack exchange,提问作者Ben Smith
相关产品推荐
相关产品推荐

