System.Text.Json - Serialize array of third-party Enum to array of strings

Viewed 62

suppose I have the following DTO:

public class FooDto
{
    public string Bar { get; set; }
    public DayOfWeek[] Days { get; set; }
}

In order to comply with the corresponding API, this DTO needs to serialize to json like this:

{
    "bar": "someString",
    "days": ["Monday", "Friday", "Sunday"]
}

Without any further actions the same DTO would serialize like this:

{
    "bar": "someString",
    "days": [1, 5, 0]
}

My Question:
Is there a way to use System.Text.Json in order to serialize an array of a third-party Enums like System.DayOfWeek as an array of it's string values? I am specifically not looking for a solution using json.net (Newtonsoft).


My Ideas that didn't work out:

  • Using [JsonConverter(typeof(JsonStringEnumConverter))] does not work on arrays.
  • In this case it's recommended to put the annotation directly above the Enum itself. This isn't possible since it's a thrid-party Enum.
  • I can't simply create a "proxy" for System.DayOfWeek since Enums don't support inheritance.
  • I could create my own DayOfWeekDto and write a mapper from System.DayOfWeek to DayOfWeekDto and vice versa, but this "solution" doesn't seem elegant at all.

Ideas for simple solutions that don't include Newtonsoft would be very welcome :)

2 Answers

Ok, this isn't an exactly answer to your question, more advice which others may disagree with.

Experience has shown me that using Enums with 3rd parties can cause a lot of trouble.

For example if the 3rd party returns a status on an object and then later adds a new status which isn't in your Enum when you try and deserialise it your system can just fall over (even if you would have just ignored it because it's not at the status you are interested in).

So what's the alternative?

Simple, create your Enum but don't use it for property types, instead set your property type to string. When assigning or comparing to your property type you would then use MyEnum.SomeValue.ToString(). Essentially your Enum just becomes a set of constants.

This has the added benefit that when you serialise you get the string value in the JSON.

If you have a .NET API you can enable this behaviour globally like so:

services
    .AddControllers()
    .AddJsonOptions(options => options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()));

However, if you are using the serializer specifically, you can use it like so:

var options = new JsonSerializerOptions()
{
    Converters = { new JsonStringEnumConverter() }
};

var x = JsonSerializer.Serialize(yourObj, options);
Related