I have an application that composes algorithms. Each algorithm consists of a sequence of steps. Steps have a very similar structure, only difference being a single property that can be one of many enum
types.
There are dozens of algorithms with hundreds of steps each. I do not want to use polymorphism as this would make the code base huge.
When using generics, the code below compiles, but produces the following output:
{"Steps":[{"Type":"Type1","Value":{}},{"Type":"Type2","Value":{}}]}
Instead of:
{"Steps":[{"Type":"Type1","Value":"Bla"},{"Type":"Type2","Value":"Etc"}]}
How can I set the System.Text.Json serializer so that it serializes the enums?
using System.Text.Json;
using System.Text.Json.Serialization;
Algorithm algorithm1 = new Algorithm();
algorithm1.Steps = new List<Step<Enum>>()
{
new Step<Enum>() { Type = AlgorithmType.Type1, Value = Options1.Bla },
new Step<Enum>() { Type = AlgorithmType.Type2, Value = Options2.Etc }
};
JsonSerializerOptions options = new JsonSerializerOptions();
options.Converters.Add(new JsonStringEnumConverter());
var result = JsonSerializer.Serialize(algorithm1, options);
Console.WriteLine(result);
public class Algorithm
{
public List<Step<Enum>> Steps { get; set; }
}
public class Step<T> where T : Enum
{
public AlgorithmType Type { get; set; }
public T? Value { get; set; }
}
public enum AlgorithmType
{
Undefined = 0,
Type1 = 1,
Type2 = 2,
// elided
Type100 = 100
}
public enum Options1
{
Undefined = 0,
Bla = 1,
YadaYada = 2
}
public enum Options2
{
Undefined = 0,
Etc = 1,
Eg = 2
}
It can be done with a custom converter:
public class CustomEnumConverter : JsonConverter<Enum> {
public override Enum Read(
ref Utf8JsonReader reader,
Type typeToConvert,
JsonSerializerOptions options)
=> throw new NotSupportedException();
public override void Write(
Utf8JsonWriter writer,
Enum value,
JsonSerializerOptions options)
=> writer.WriteStringValue(value.ToString());
}
Usage:
var steps = new List<Step<Enum>> {
new Step<Enum>(Foo.Bar),
new Step<Enum>(Zan.Gor)
};
var opts = new JsonSerializerOptions {
Converters = { new CustomEnumConverter() }
};
var json = JsonSerializer.Serialize(steps, opts);
public record Step<T>(T Value) where T : Enum;
public enum Foo { Bar, Qux }
public enum Zan { Qel, Gor }
Result:
[{"Value":"Bar"},{"Value":"Gor"}]
I doubt that this is the right approach though. How would you go about deserializing these enums?