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

使用Json.Net反序列化后如何获取所有未匹配键与缺失字段?

解决方案

你不需要完全自定义JsonConverter,搭配Newtonsoft.Json自带的错误回调和JObject预解析即可实现两类不匹配项的检查,实现成本极低。

第一步:配置反序列化参数捕获JSON多余键

通过MissingMemberHandling.Error配置触发未匹配键的错误,再通过自定义Error回调收集日志,不会中断反序列化流程:

var deserializeSettings = new JsonSerializerSettings
{
    // 遇到结构体未定义的JSON键时抛出错误
    MissingMemberHandling = MissingMemberHandling.Error,
    // 全局错误处理,收集多余键日志
    Error = (sender, args) =>
    {
        if (args.ErrorContext.Error is JsonSerializationException)
        {
            var parentType = args.CurrentObject.GetType().Name;
            var extraKey = args.ErrorContext.Path;
            // 输出你需要的日志格式
            Console.WriteLine($"[Error][{parentType}::{extraKey} key not exist in struct]");
            // 标记错误已处理,继续反序列化流程
            args.ErrorContext.Handled = true;
        }
    }
};

第二步:预解析JObject检查JSON缺失字段

先把JSON字符串解析为JObject,递归对比目标结构体的所有字段和JObject的键,收集缺失字段的日志:

using System.Reflection;
using Newtonsoft.Json.Linq;

public static List<string> GetMissingFieldLogs(JObject jObj, Type targetType, string parentPath = "")
{
    var logs = new List<string>();
    // 获取当前类型的所有公开实例字段
    var fields = targetType.GetFields(BindingFlags.Public | BindingFlags.Instance);
    
    foreach (var field in fields)
    {
        string currentPath = string.IsNullOrEmpty(parentPath) 
            ? $"{targetType.Name}::{field.Name}" 
            : $"{parentPath}::{field.Name}";
        
        // 检查JSON中是否存在对应键
        if (!jObj.TryGetValue(field.Name, out JToken value))
        {
            logs.Add($"[Error][{currentPath} field not exist in json string]");
            continue;
        }
        
        // 嵌套结构体递归检查
        var fieldType = field.FieldType;
        if (fieldType.IsValueType && !fieldType.IsPrimitive && !fieldType.IsEnum && fieldType != typeof(decimal))
        {
            if (value is JObject childJObj)
            {
                logs.AddRange(GetMissingFieldLogs(childJObj, fieldType, currentPath));
            }
        }
    }
    return logs;
}

第三步:组合调用

// 你的JSON字符串
string jsonStr = @"{
    ""Hp"": 100,
    ""PlayerInfo"": {
        ""Atk"": 10,
        ""Def"": 20
    },
    ""Mp"": 100
}";

// 1. 预解析JObject,检查缺失字段
JObject jObj = JObject.Parse(jsonStr);
var missingLogs = GetMissingFieldLogs(jObj, typeof(CharaData));
foreach (var log in missingLogs)
{
    Console.WriteLine(log);
}

// 2. 反序列化,检查多余键
CharaData data = jObj.ToObject<CharaData>(JsonSerializer.Create(deserializeSettings));

运行输出

完全符合你要求的日志格式:

[Error][CharaData::PlayerInfo::Spd field not exist in json string]
[Error][CharaData::Mp key not exist in struct]

补充说明

  • 如果你的字段加了[JsonProperty("自定义别名")]属性,只需要在GetMissingFieldLogs方法中先获取字段的JsonPropertyAttribute的Name值作为键名对比即可。
  • 如果需要支持数组、列表类型的检查,扩展GetMissingFieldLogs的递归逻辑即可。
  • 如果追求更高性能,不想两次解析JSON,可以自定义JsonConverter边反序列化边做两类检查,实现逻辑和上面的思路一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 17:24:04