ASP.NET中序列化List<KeyValuePair<string,string>>至YAML格式异常问题
问题:ASP.NET(C#)修改YAML文件时格式异常
现有YAML文件内容:
pcap: - interface: eth0 - interface: default
通过C#代码向其中添加新的interface条目,但生成的YAML出现Key和Value字段,格式不符合预期,且无法用Dictionary处理重复键的问题。
错误代码:
var path = "/etc/suricata/suricata_cp.yaml"; var deserializer = new YamlDotNet.Serialization.Deserializer(); try { using var reader = new StreamReader(path); var obj = deserializer.Deserialize<Dictionary<object, object>>(reader); var doctrine = obj["pcap"]; List<object> pcap = (List<object>)obj["pcap"]; List<KeyValuePair<string,string>> addInterfaces = new List<KeyValuePair<string, string>>(); foreach(var cli in clientReq) addInterfaces.Add(new KeyValuePair<string, string>("interface",cli)); pcap.Add(addInterfaces); doctrine = pcap; reader.Close(); using var writer = new StreamWriter(path); // Save Changes var serializer = new YamlDotNet.Serialization.Serializer(); serializer.Serialize(writer, obj); }
错误输出结果:
pcap: - interface: eth0 - interface: default - - Key: interface Value: eth3
问题原因
- 直接将
List<KeyValuePair<...>>添加到pcap列表,序列化时会把键值对的结构原样输出成Key和Value字段; - 原YAML中每个
interface条目是单键的匿名对象/字典,而非键值对集合。
修复方案
方案1:使用动态类型(简洁灵活)
直接创建包含interface属性的匿名对象添加到列表,匹配原YAML格式:
var path = "/etc/suricata/suricata_cp.yaml"; var deserializer = new YamlDotNet.Serialization.Deserializer(); try { using var reader = new StreamReader(path); dynamic obj = deserializer.Deserialize(reader); List<dynamic> pcapList = obj.pcap as List<dynamic>; foreach(var cli in clientReq) { // 每个对象对应一条- interface: xxx条目 pcapList.Add(new { @interface = cli }); } using var writer = new StreamWriter(path); var serializer = new YamlDotNet.Serialization.Serializer(); serializer.Serialize(writer, obj); } catch (Exception ex) { // 按需处理异常 }
方案2:自定义类实现类型安全
定义对应YAML结构的类,通过类映射保证序列化格式:
// 定义匹配interface条目的类 public class InterfaceEntry { [YamlMember(Alias = "interface")] public string InterfaceName { get; set; } } // 修改后的业务代码 var path = "/etc/suricata/suricata_cp.yaml"; var deserializer = new YamlDotNet.Serialization.DeserializerBuilder() .WithNamingConvention(CamelCaseNamingConvention.Instance) .Build(); try { using var reader = new StreamReader(path); var obj = deserializer.Deserialize<Dictionary<string, object>>(reader); var pcapList = deserializer.Deserialize<List<InterfaceEntry>>(obj["pcap"].ToString()); foreach(var cli in clientReq) { pcapList.Add(new InterfaceEntry { InterfaceName = cli }); } obj["pcap"] = pcapList; using var writer = new StreamWriter(path); var serializer = new YamlDotNet.Serialization.SerializerBuilder() .WithNamingConvention(CamelCaseNamingConvention.Instance) .Build(); serializer.Serialize(writer, obj); } catch (Exception ex) { // 按需处理异常 }
关键注意事项
- 不要批量添加键值对列表,而是逐个添加单键对象,每个对象对应一条
- interface: xxx条目; - 使用动态类型或自定义类能更好匹配YAML结构,避免强制类型转换的潜在问题。
内容的提问来源于stack exchange,提问作者prog_prog
相关产品推荐
相关产品推荐

