Search code examples
c#system.text.jsonnamevaluecollection

Serializing NameValueCollection as Dictionary using System.Text.Json


I'm sure there's a converter I need to implement to handle NameValueCollection objects using System.Text.Json (note: I've seen the answers related to legacy JavaScriptSerializer).

This:

NameValueCollection nvc = new NameValueCollection();
nvc.Add("foo", "bar");
nvc.Add("foo", "bar2");
nvc.Add("bar", "baz");

string json = SerializationHelper.SerializeJson(nvc, true);
Console.WriteLine(json);

Produces:

[
  "foo",
  "bar"
]

Instead of what I would want:

{
  "foo": "bar",
  "foo": "bar2",
  "bar": "baz"
}

Or even:

{
  "foo": "bar,bar2",
  "bar": "baz"
}

Serialization method looks like this:

public static string SerializeJson(object obj, bool pretty)
{
    if (obj == null) return null;
    string json;

    JsonSerializerOptions options = new JsonSerializerOptions();
    options.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
    options.Converters.Add(new ExceptionConverter<Exception>());

    if (pretty)
    {
        options.WriteIndented = true;
        json = JsonSerializer.Serialize(obj, options);
    }
    else
    {
        options.WriteIndented = false;
        json = JsonSerializer.Serialize(obj, options);
    }

    return json;
}

Any thoughts on how to get the desired behavior or a converter that would handle this case?


Solution

  • You can write simple custom converter which will transform the NameValueCollection into dictionary and serialize it:

    class MyConv : System.Text.Json.Serialization.JsonConverter<NameValueCollection>
    {
        public override NameValueCollection? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) => throw new NotImplementedException();
    
        public override void Write(Utf8JsonWriter writer, NameValueCollection value, JsonSerializerOptions options)
        {
            var val = value.Keys.Cast<string>()
                .ToDictionary(k => k, k => string.Join(", ", value.GetValues(k)));
            System.Text.Json.JsonSerializer.Serialize(writer, val);
        }
    }
    

    And add it to options:

    options.Converters.Add(new MyConv());