如何将JSON字符串以结构化数据形式记录日志而非字符串?
实现方案
下面是几种将JSON字符串作为结构化数据写入日志的可行方法:
1. 反序列化为ExpandoObject
无需提前定义实体类,适合结构不固定的JSON场景:
using System.Dynamic; using Newtonsoft.Json; var dataJson = "{\"key1\": \"value1\", \"key2\": \"value2\"}"; dynamic data = JsonConvert.DeserializeObject<ExpandoObject>(dataJson); using (LogContext.PushProperty("data", data)) { _logger.LogInformation("balabala"); }
输出的data字段会是结构化的JSON对象,不会包含多余的类型标识。
2. 正确反序列化为Dictionary<string, object>
若使用System.Text.Json,需指定反序列化选项以保留嵌套结构:
using System.Text.Json; var dataJson = "{\"key1\": \"value1\", \"key2\": \"value2\"}"; var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; var data = JsonSerializer.Deserialize<Dictionary<string, object>>(dataJson, options); using (LogContext.PushProperty("data", data)) { _logger.LogInformation("balabala"); }
Serilog会自动将字典序列化为结构化的JSON对象,而非字符串形式。
3. 定义强类型实体类(推荐固定结构场景)
如果JSON结构固定,定义对应实体类是最清晰且性能更优的方式:
public class LogData { public string Key1 { get; set; } public string Key2 { get; set; } } // 反序列化 var dataJson = "{\"key1\": \"value1\", \"key2\": \"value2\"}"; var data = JsonConvert.DeserializeObject<LogData>(dataJson); using (LogContext.PushProperty("data", data)) { _logger.LogInformation("balabala"); }
这种方式输出的data字段结构明确,类型信息清晰。
关键注意点
- 绝对不要直接将JSON字符串传入
PushProperty,必须传入已完成反序列化的对象(动态对象、字典或实体类)。 - 若使用
Newtonsoft.Json,可配置Serilog使用该序列化器保证一致性:
Log.Logger = new LoggerConfiguration() .WriteTo.Console(new JsonFormatter(renderMessage: true)) .Destructure.With<NewtonsoftJsonDestructuringPolicy>() .CreateLogger();
内容的提问来源于stack exchange,提问作者imeatenup
相关产品推荐
相关产品推荐

