Search code examples
c#json.net-coresystem.text.jsonjsonconverter

Custom JsonConverter (System.Text.Json) producing invalid json


This is the class I want to custom serialize:

public class MyClass
{
    public string Key {get; set;}
    public IEnumerable<string> Value {get; set;}
}

If I've got a list of it, normal serialization would produce the following output:

[
    {
        "Key": "MyKey1",
        "Value": [
            "Value1",
            "Value2"
        ]
    },
    {
        "Key": "MyKey2",
        "Value": [
            "Value3",
            "Value4"
        ]
    }
]

What I want is to remove the property-names from the json-result like so:

[    
    {
        "MyKey1": [
            "Value1",
            "Value2"
        ]
    },
    {
        "MyKey2": [
            "Value3",
            "Value4"
        ]
    }
]

So i decided to implement a custom JsonConverter like so:

public class MyClassJsonConverter : JsonConverter<MyClass>
{
    public override void Write(Utf8JsonWriter writer, MyClass value, JsonSerializerOptions options)
    {
        //custom code goes here
        writer.WriteStartArray(value.Key);

        foreach (var val in value.Value)
            writer.WriteStringValue(val);

        writer.WriteEndArray();
    }
}

But this produces invalid json:

[
    "MyKey1": [
        "Value1",
        "Value2"
    ],
   "MyKey2": [
       "Value3",
       "Value4"
    ]
]

How to resolve this?


Solution

  • You should use WriteStartObject() before writing the array and WriteEndObject() after

    public override void Write(Utf8JsonWriter writer, MyClass value, JsonSerializerOptions options)
    {
        writer.WriteStartObject();
    
        //custom code goes here
        writer.WriteStartArray(value.Key);
    
        foreach (var val in value.Value)
            writer.WriteStringValue(val);
    
        writer.WriteEndArray();
        writer.WriteEndObject();
    }
    

    Then the following code

    var list = new List<MyClass>
    {
        new MyClass { Key = "MyKey1", Value = new[] { "Value1", "Value2" } },
        new MyClass { Key = "MyKey2", Value = new[] { "Value3", "Value4" } }
    };
    
    var options = new JsonSerializerOptions();
    options.Converters.Add(new MyClassJsonConverter());
    var json = JsonSerializer.Serialize(list, options);
    

    gives you the expected JSON

    [
        {
            "MyKey1": [
                "Value1",
                "Value2"
            ]
        },
        {
            "MyKey2": [
                "Value3",
                "Value4"
            ]
        }
    ]