使用ConfigurationBuilder读取JSON配置时列表null值绑定异常问题
问题现象
在appsettings.json中配置可空枚举类型的列表属性时,JSON数组内写入的null值会在配置绑定阶段被自动过滤,无法填充到目标列表属性中;但代码中手动调用列表的Add(null)方法可以正常添加null值,说明属性本身支持存储null,问题出在默认配置绑定逻辑。
最小复现代码
C# 逻辑
using Microsoft.Extensions.Configuration; using System; using System.Collections.Generic; class Program { static void Main(string[] args) { var builder = new ConfigurationBuilder() .AddJsonFile($"appsettings.json"); var config = builder.Build(); var test = config.GetRequiredSection("Settings").Get<Settings>(); // 手动添加null可正常执行 test.EnumList.Add(null); } } class Settings { public enum EnumValues { Value1, Value2 } public List<EnumValues?> EnumList { get; set; } }
appsettings.json 配置
{ "Settings": { "EnumList" : [null, "Value1"] } }
实际绑定结果:加载得到的
EnumList仅包含EnumValues.Value11个元素,JSON中配置的首项null被丢弃。
问题原因
Microsoft.Extensions.Configuration默认的绑定器内置了空值过滤逻辑,处理集合类型绑定时会自动跳过配置源中读取到的null项,该逻辑没有对Nullable<T>类型(包括可空枚举)的集合做特殊适配,因此无法直接识别并保留JSON数组中的null值。
实现方案
方案1:直接反序列化配置节原始内容(推荐,改动最小)
绕开默认绑定器的空值过滤逻辑,先将配置节读取为JSON节点,再用JSON反序列化器转换为目标配置对象,反序列化时配置保留null值即可。
.NET Core 3.0及以上版本内置System.Text.Json,无需额外引入依赖,修改后的读取逻辑如下:
using System.Text.Json; using System.Text.Json.Nodes; // 替换原有的Get<Settings>()调用 var settingsNode = config.GetRequiredSection("Settings").Get<JsonNode>(); var test = settingsNode.Deserialize<Settings>(new JsonSerializerOptions { // 反序列化时不忽略null值 DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.Never });
执行后test.EnumList会按JSON文件中的顺序得到2个元素:首项为null,第二项为EnumValues.Value1,完全符合预期。
方案2:自定义全局配置绑定规则
如果项目中存在大量同类配置需求,可以自定义配置绑定转换器,重写集合绑定阶段的null值处理逻辑,针对可空值类型的集合保留null项。该方案无需修改单个配置的读取代码,但实现复杂度较高,适合大型全局统一配置场景使用。
注意:不要使用空字符串代替null写入JSON配置,枚举类型绑定空字符串会抛出格式转换异常,无法实现和null一致的效果。
内容的提问来源于stack exchange,提问作者EatATaco

