C# Json.NET Render Flags Enum as String Array

You have to implement your own converter. Here's an example (a particularly dirty and hacky way of doing it, but it serves as a good demo):

public class FlagConverter : JsonConverter
{
    public override object ReadJson(JsonReader reader,  Type objectType, Object existingValue, JsonSerializer serializer)
    {
        //If you need to deserialize, fill in the code here
        return null;
    }

    public override void WriteJson(JsonWriter writer, Object value, JsonSerializer serializer)
    {
        var flags = value.ToString()
            .Split(new[] { ", " }, StringSplitOptions.RemoveEmptyEntries)
            .Select(f => $"\"{f}\"");

        writer.WriteRawValue($"[{string.Join(", ", flags)}]");
    }

    public override bool CanConvert(Type objectType)
    {
        return true;
    }
}

Now decorate your enum like this:

[Flags]
[JsonConverter(typeof(FlagConverter))]
public enum F
{
    Val1 = 1,
    Val2 = 2,
    Val4 = 4,
    Val8 = 8
}

And your example serialisation code will now output this:

{"Flags":["Val1", "Val4"]}

Decorate your enum

[Flags]
[JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]
public enum F
{
    Val1 = 1,
    Val2 = 2,
    Val4 = 4,
    Val8 = 8
}

Output:

{"Flags":"Val1, Val4"}

I realise the JSON is not an array as in your question, wasn't sure if this was required since this is also valid JSON.


I used @DavidG's answer above, but needed an implementation for ReadJson. Here's what I put together:

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
    int outVal = 0;
    if (reader.TokenType == JsonToken.StartArray)
    {
        reader.Read();
        while (reader.TokenType != JsonToken.EndArray)
        {
            outVal += (int)Enum.Parse(objectType, reader.Value.ToString());
            reader.Read();
        }
    }
    return outVal;
}