You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修改Serilog解构复杂对象时的默认分隔符为等号?

可以实现,通过自定义Serilog的格式化逻辑即可替换解构对象的键值分隔符

Serilog默认的解构输出使用冒号分隔属性名和值,要改成等号,有两种常用实现方式:

方式一:正则替换输出文本(简单场景适用)

通过自定义ITextFormatter捕获原始日志输出,再用正则替换属性的冒号为等号:

using Serilog;
using Serilog.Events;
using Serilog.Formatting;
using Serilog.Formatting.Display;
using System.IO;

public class EqualSignObjectFormatter : ITextFormatter
{
    private readonly MessageTemplateTextFormatter _innerFormatter;

    public EqualSignObjectFormatter(string outputTemplate = "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}")
    {
        _innerFormatter = new MessageTemplateTextFormatter(outputTemplate);
    }

    public void Format(LogEvent logEvent, TextWriter output)
    {
        using var stringWriter = new StringWriter();
        _innerFormatter.Format(logEvent, stringWriter);
        var originalOutput = stringWriter.ToString();
        
        // 匹配属性名:值的格式,替换为属性名=值
        var modifiedOutput = System.Text.RegularExpressions.Regex.Replace(originalOutput, @"(\w+):""([^""]+)""", "$1=\"$2\"");
        output.Write(modifiedOutput);
    }
}

配置Logger时指定该格式化器:

public class myClass
{
    public void myMethod()
    {
        var logger = new LoggerConfiguration()
            .WriteTo.EventLog("myapp", formatter: new EqualSignObjectFormatter())
            .CreateLogger();
        
        var myComplexObject = new 
        {
            property1 = "prop1",
            property2 = "prop2"
        };
        logger.Information("{@complex}", myComplexObject);
    }
}

注意:这种方式适合属性值不含引号的简单场景,若值中有引号会导致正则匹配错误。

方式二:自定义解构策略(严谨场景适用)

实现IDestructuringPolicy完全控制对象的解构输出逻辑,避免正则的局限性:

using Serilog.Core;
using Serilog.Events;
using System.Reflection;

public class EqualSignDestructuringPolicy : IDestructuringPolicy
{
    public bool TryDestructure(object value, ILogEventPropertyValueFactory propertyValueFactory, out LogEventPropertyValue result)
    {
        // 跳过值类型、字符串等不需要解构的类型
        if (value == null || value.GetType().IsValueType || value is string)
        {
            result = null;
            return false;
        }

        // 获取对象的所有属性并转换为LogEventProperty
        var properties = value.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)
            .Select(p => new LogEventProperty(p.Name, propertyValueFactory.CreatePropertyValue(p.GetValue(value), true)));
        
        // 使用自定义的StructureValue控制输出格式
        result = new CustomStructureValue(properties);
        return true;
    }

    // 自定义StructureValue重写渲染逻辑,用等号分隔键值
    private class CustomStructureValue : StructureValue
    {
        public CustomStructureValue(IEnumerable<LogEventProperty> properties) : base(properties)
        {
        }

        public override void Render(TextWriter output, string format = null, IFormatProvider formatProvider = null)
        {
            output.Write("{ ");
            var isFirst = true;
            foreach (var prop in Properties)
            {
                if (!isFirst)
                    output.Write(", ");
                
                output.Write(prop.Name);
                output.Write("=\"");
                prop.Value.Render(output, format, formatProvider);
                output.Write("\"");
                isFirst = false;
            }
            output.Write(" }");
        }
    }
}

配置Logger时添加该解构策略:

public class myClass
{
    public void myMethod()
    {
        var logger = new LoggerConfiguration()
            .Destructure.With<EqualSignDestructuringPolicy>()
            .WriteTo.EventLog("myapp")
            .CreateLogger();
        
        var myComplexObject = new 
        {
            property1 = "prop1",
            property2 = "prop2"
        };
        logger.Information("{@complex}", myComplexObject);
    }
}

两种方式都能实现你想要的输出:{ complex:{ property1="prop1", property2="prop2" }}

内容的提问来源于stack exchange,提问作者Breakwin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 07:33:13