如何让JsonConvert.DeserializeObject遇类型错误不中断并收集所有错误?
实现带全局错误收集的JSON反序列化
需求说明
需要反序列化包含多种类型(int、float、string、Guid)属性的类,满足:
- 当值与预期类型不匹配时,将错误添加至错误列表
- 继续执行反序列化,收集全部错误而非仅第一个错误
示例代码
目标实体类
修正原语法错误后的Row记录类型:
public record Row { [JsonProperty("columnName")] public string? ColumnName { get; set; } [JsonProperty("entityCode")] public Guid? EntityCode { get; set; } [JsonProperty("numberValue")] public float? NumberValue { get; set; } [JsonProperty("integerValue")] public int? IntegerValue { get; set; } [JsonProperty("booleanValue")] public bool? BooleanValue { get; set; } }
待反序列化的JSON(修正语法错误)
{ "Row": [ { "columnName": "category", "entityCode": "not a guid" }, { "columnName": "numberValue", "numberValue": "not a number" }, { "columnName": "value", "stringValue": 104.28398 }, { "columnName": "value", "booleanValue": "not a bool" } ] }
实现方案
使用Newtonsoft.Json(Json.NET)的JsonSerializerSettings配置错误处理逻辑,实现全局错误收集并继续反序列化:
1. 定义错误信息实体
用于存储反序列化错误的详细信息:
public class DeserializationError { public string Path { get; set; } = string.Empty; public string Message { get; set; } = string.Empty; public string PropertyName { get; set; } = string.Empty; }
2. 配置反序列化参数并收集错误
通过ContinueOnError开启错误续传,订阅Error事件收集所有错误:
// 初始化错误列表 var deserializationErrors = new List<DeserializationError>(); // 配置序列化设置 var serializerSettings = new JsonSerializerSettings { // 遇到错误不终止反序列化 ContinueOnError = true, // 可选:捕获未知属性错误(如果需要) MissingMemberHandling = MissingMemberHandling.Error, Error = (sender, args) => { // 提取错误详情并加入列表 deserializationErrors.Add(new DeserializationError { Path = args.ErrorContext.Path, Message = args.ErrorContext.Error.Message, PropertyName = args.ErrorContext.Member ?? string.Empty }); // 标记错误已处理,避免抛出异常 args.ErrorContext.Handled = true; } }; // 执行反序列化 var jsonString = "上述完整JSON字符串"; var rows = JsonConvert.DeserializeObject<IList<Row>>(jsonString, serializerSettings);
效果说明
执行上述代码后:
rows会被正常反序列化,类型不匹配的属性会被设为对应可空类型的默认值(null)deserializationErrors列表会包含所有反序列化错误,例如:Row[0].entityCode:无法将字符串"not a guid"转换为Guid类型Row[1].numberValue:无法将字符串"not a number"转换为float类型Row[2].stringValue:找不到成员'stringValue'(当开启MissingMemberHandling.Error时)Row[3].booleanValue:无法将字符串"not a bool"转换为bool类型
内容的提问来源于stack exchange,提问作者Emilija Vilija Trečiokaitė
相关产品推荐
相关产品推荐

