如何从appsettings.json中获取List<MyField>?参数字段反序列化失败导致列表为空的问题排查
这个问题的核心原因很明确:你的JSON配置里parameters是一个包含key/value键值对的对象数组,但MyField类里对应的属性是IDictionary<string, string>类型。不管是.NET默认的配置绑定,还是Newtonsoft.Json的反序列化,都没办法自动把这种数组结构转换成字典,所以反序列化失败,最终导致整个List<MyField>返回空。
下面提供两种可行的解决方案,你可以根据自己的场景选择:
方案一:自定义Json转换器(无需修改类结构)
通过创建一个自定义的JsonConverter,告诉序列化程序如何把数组转换成字典。
首先定义转换器类:
public class KeyValueArrayToDictionaryConverter : JsonConverter<IDictionary<string, string>> { public override IDictionary<string, string>? ReadJson(JsonReader reader, Type objectType, IDictionary<string, string>? existingValue, bool hasExistingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) return null; // 先把数组反序列化成键值对列表,再转成字典 var keyValueList = serializer.Deserialize<List<(string key, string value)>>(reader); return keyValueList?.ToDictionary(kvp => kvp.key, kvp => kvp.value); } public override void WriteJson(JsonWriter writer, IDictionary<string, string>? value, JsonSerializer serializer) { if (value == null) { writer.WriteNull(); return; } // 写回JSON时,把字典转成原来的数组格式 serializer.Serialize(writer, value.Select(kvp => new { key = kvp.Key, value = kvp.Value })); } }
然后在MyField类的parameters属性上标记使用这个转换器:
public class MyField { [JsonProperty] public string? name { get; set; } [JsonProperty] public string? type { get; set; } [JsonConverter(typeof(KeyValueArrayToDictionaryConverter))] public IDictionary<string,string>? parameters { get; set; } }
这样配置绑定/反序列化时,就会自动把数组转换成字典,你原来的读取代码config.GetSection("MyFields").Get<List<MyField>>()就能正常工作了。
方案二:修改类结构匹配JSON(更直观易维护)
既然JSON里parameters是数组,那我们先让类的结构完全匹配它,再通过一个只读属性来获取字典,方便业务代码使用:
首先定义数组项的类:
public class ParameterEntry { [JsonProperty("key")] public string? Key { get; set; } [JsonProperty("value")] public string? Value { get; set; } }
然后修改MyField类:
public class MyField { [JsonProperty] public string? name { get; set; } [JsonProperty] public string? type { get; set; } [JsonProperty("parameters")] public List<ParameterEntry>? ParameterEntries { get; set; } // 只读属性,把数组转成字典供业务使用 public IDictionary<string, string>? Parameters { get => ParameterEntries?.ToDictionary(p => p.Key!, p => p.Value!); } }
这种方式的优点是类结构和JSON完全对应,后期维护时更直观,不需要理解自定义转换器的逻辑。缺点是需要多定义一个类,并且业务代码里要使用Parameters只读属性来获取字典。
额外提示
如果你的项目使用的是.NET Core/.NET 5+的默认配置系统,确保你已经正确引用了Newtonsoft.Json的配置提供器(如果用的是默认的System.Text.Json,可能需要调整转换器的写法,不过上面的方案针对Newtonsoft.Json是完全有效的)。
内容的提问来源于stack exchange,提问作者Abheet Pandey

