Serializing a List<KeyValuePair<string, string>> not working properly

136 views Asked by At

I have a yaml file that looks like this:

pcap:
- interface: eth0
- interface: default

I would like, through my ASP.NET (C#) program, to add to this section, more lines according to what the user requests. So my code looks like this:

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);
}

But the result after adding one line to the file (in case I added only one), looks like this:

pcap:
- interface: eth0
- interface: default
- - Key: interface
    Value: eth3

I don't want "key", "value" to be written. I want it to be written like the first 2 lines. In addition, I cannot use the dictionary type because I have identical values in the key (I have seen such solutions in similar questions, but for me dictionary does not help)

1

There are 1 answers

0
Guru Stron On

Actually I would argue that this is working as expected, usual convention is to handle dictionaries (the same you can see in json serializers like System.Text.Json and Newtonsoft.Json), not a collection of KeyValuePairs. In this case just use the serialization/deserialization to/from classes:

public class Root
{
    public List<Pcap> Pcap { get; set; }
}

public class Pcap
{
    public string Interface { get; set; }
}
var yaml = """
pcap:
- interface: eth0
- interface: default
""";

var deserializer = new DeserializerBuilder()
    .WithNamingConvention(CamelCaseNamingConvention.Instance)
    .Build();
var pcaps = deserializer.Deserialize<Root>(yaml);
pcaps.Pcap.Add(new Pcap{Interface = "some other interface"});

var serializer = new SerializerBuilder()
    .WithNamingConvention(CamelCaseNamingConvention.Instance)
    .Build();
var serialize = serializer.Serialize(pcaps);

Result in serialize variable:

pcap:
- interface: eth0
- interface: default
- interface: some other interface