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

在C#中使用System.Text.Json反序列化JSON至字典的问题

问题分析与解决方案

核心问题总结

你的代码无法成功反序列化的原因有以下几点:

  1. JSON结构外层包含FullSchedule属性,并非直接对应字典对象,直接反序列化为Dictionary会匹配失败
  2. System.Text.Json默认不支持反序列化为Stack<T>类型(仅原生支持列表、数组等常见集合)
  3. 文件存在性判断逻辑错误(用Directory.Exists检查文件路径,而非File.Exists)
  4. 反序列化类型与返回类型不匹配(Stack<Training?> vs Stack<Training>)

步骤1:定义必要的基础类型

确保你的枚举Dag和类Training与JSON字段完全匹配:

public enum Dag
{
    Maandag,
    Dinsdag,
    Woensdag,
    Donderdag,
    Vrijdag,
    Zaterdag,
    Zondag
}

public class Training
{
    public string Name { get; set; }
    public string Description { get; set; }
    public int Trainingsort { get; set; }
    public int Hours { get; set; }
    public int Minutes { get; set; }
}

步骤2:自定义Stack转换器

由于System.Text.Json不原生支持Stack<T>,需要实现自定义转换器:

public class StackConverter<T> : JsonConverter<Stack<T>>
{
    public override Stack<T> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        // 先反序列化为List,再转换为Stack
        var list = JsonSerializer.Deserialize<List<T>>(ref reader, options);
        return list != null ? new Stack<T>(list) : new Stack<T>();
    }

    public override void Write(Utf8JsonWriter writer, Stack<T> value, JsonSerializerOptions options)
    {
        // 序列化时将Stack转为List输出
        JsonSerializer.Serialize(writer, value.ToList(), options);
    }
}

步骤3:修正反序列化方法

以下是完整的修正代码,包含JSON结构匹配、转换器配置和错误处理优化:

public static Dictionary<Dag, Stack<Training>> ReadJSON(string path)
{
    string jsonFilePath = $@"{path}.json";
    
    // 修正文件存在性判断逻辑
    if (!File.Exists(jsonFilePath))
        throw new ArgumentException($"指定的JSON文件不存在:{jsonFilePath}");

    string scheduleJson;
    try
    {
        // 简化文件读取逻辑
        scheduleJson = File.ReadAllText(jsonFilePath);
    }
    catch (Exception ex)
    {
        throw new Exception($"读取文件失败:{ex.Message}", ex);
    }

    var serializerOptions = new JsonSerializerOptions
    {
        // 添加Stack转换器
        Converters = { new StackConverter<Training>() },
        // 允许枚举与JSON键大小写不匹配(可选,根据你的枚举定义调整)
        PropertyNameCaseInsensitive = true
    };

    // 先解析外层的FullSchedule容器
    var scheduleWrapper = JsonSerializer.Deserialize<ScheduleWrapper>(scheduleJson, serializerOptions);
    return scheduleWrapper?.FullSchedule ?? new Dictionary<Dag, Stack<Training>>();
}

// 匹配JSON外层结构的包装类
public class ScheduleWrapper
{
    public Dictionary<Dag, Stack<Training>> FullSchedule { get; set; }
}

可选方案:不使用包装类

如果不想定义ScheduleWrapper,可以直接用JsonDocument提取FullSchedule节点:

public static Dictionary<Dag, Stack<Training>> ReadJSON(string path)
{
    string jsonFilePath = $@"{path}.json";
    
    if (!File.Exists(jsonFilePath))
        throw new ArgumentException($"指定的JSON文件不存在:{jsonFilePath}");

    string scheduleJson;
    try
    {
        scheduleJson = File.ReadAllText(jsonFilePath);
    }
    catch (Exception ex)
    {
        throw new Exception($"读取文件失败:{ex.Message}", ex);
    }

    var serializerOptions = new JsonSerializerOptions
    {
        Converters = { new StackConverter<Training>() },
        PropertyNameCaseInsensitive = true
    };

    using var jsonDoc = JsonDocument.Parse(scheduleJson);
    var fullScheduleElement = jsonDoc.RootElement.GetProperty("FullSchedule");
    return JsonSerializer.Deserialize<Dictionary<Dag, Stack<Training>>>(fullScheduleElement.GetRawText(), serializerOptions);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 12:50:23