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

.NET 6使用Options模式读取含Int键JSON文件的映射问题

问题根源

.NET配置系统的默认绑定逻辑不会自动将JSON中的字符串类型字典键(如"4")转换为整数类型,因此模型中Dictionary<int, CategoryMapping>和Dictionary<int, List<SubcategoryMapping>>类型的属性无法被正确解析,最终返回null。


解决方案

方案1:改用System.Text.Json直接读取(最简单)

放弃通过IConfiguration绑定,直接用System.Text.Json读取JSON文件,通过配置允许字符串转数值类型,自动处理整数键映射:

  1. 新增根模型类匹配JSON结构:
public class RootConfig
{
    public List<Sender> TestMap { get; set; }
}
  1. 读取并反序列化JSON:
using System.Text.Json;
using System.Text.Json.Serialization;

// 拼接JSON文件路径
var jsonPath = Path.Combine(AppContext.BaseDirectory, "Properties/test.json");
var jsonContent = File.ReadAllText(jsonPath);

// 配置序列化选项,允许将字符串解析为数值
var serializeOptions = new JsonSerializerOptions
{
    NumberHandling = JsonNumberHandling.AllowReadingFromString,
    PropertyNameCaseInsensitive = true // 可选,避免大小写匹配问题
};

// 反序列化获取数据
var rootConfig = JsonSerializer.Deserialize<RootConfig>(jsonContent, serializeOptions);
List<Sender> people = rootConfig.TestMap;

此方案会自动处理所有字符串形式的整数键,包括CategoryMappings和SubcategoryMappings的转换。


方案2:自定义配置绑定转换器(适配IConfiguration)

若必须使用IConfiguration绑定,可实现自定义转换器手动转换键类型:

  1. 实现通用整数键字典转换器:
using Microsoft.Extensions.Configuration;

public class IntKeyDictionaryConverter<TValue> : IConfigurationConverter<Dictionary<int, TValue>>
{
    public Dictionary<int, TValue> Convert(IConfiguration configuration)
    {
        var dict = new Dictionary<int, TValue>();
        foreach (var childSection in configuration.GetChildren())
        {
            if (int.TryParse(childSection.Key, out int key))
            {
                var value = childSection.Get<TValue>();
                dict[key] = value;
            }
        }
        return dict.Count > 0 ? dict : null;
    }
}
  1. 绑定时指定转换器:
var binderOptions = new BinderOptions
{
    Converters = 
    {
        new IntKeyDictionaryConverter<CategoryMapping>(),
        new IntKeyDictionaryConverter<List<SubcategoryMapping>>()
    }
};

List<Sender> people = Configuration.GetSection("TestMap").Get<List<Sender>>(binderOptions);

方案3:手动绑定配置节点(最灵活)

若需精细控制,可手动遍历配置节点并转换键类型:

var testMapSection = Configuration.GetSection("TestMap");
List<Sender> people = new List<Sender>();

foreach (var senderSection in testMapSection.GetChildren())
{
    var sender = new Sender
    {
        SenderID = senderSection["SenderID"],
        FeedType = senderSection["FeedType"],
        CategoryMappings = new Dictionary<int, CategoryMapping>()
    };

    // 处理CategoryMappings
    var categorySection = senderSection.GetSection("CategoryMappings");
    foreach (var catNode in categorySection.GetChildren())
    {
        if (int.TryParse(catNode.Key, out int catKey))
        {
            var categoryMapping = catNode.Get<CategoryMapping>();
            categoryMapping.SubcategoryMappings = new Dictionary<int, List<SubcategoryMapping>>();

            // 处理SubcategoryMappings
            var subcatSection = catNode.GetSection("SubcategoryMappings");
            if (subcatSection.Exists())
            {
                foreach (var subcatNode in subcatSection.GetChildren())
                {
                    if (int.TryParse(subcatNode.Key, out int subKey))
                    {
                        var subList = subcatNode.Get<List<SubcategoryMapping>>();
                        categoryMapping.SubcategoryMappings[subKey] = subList;
                    }
                }
            }

            sender.CategoryMappings[catKey] = categoryMapping;
        }
    }

    people.Add(sender);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 22:35:25