Sooner or later we would need to serialize/deserialize our lovely discriminated unions and OneOf doesn't come with built-in serialization/deserialization. OneOf.Serialization
was created mainly to solve this challange by giving convention-based serialization/deserialization when using the powerful tool OneOf.
NOTE: OneOf.Serialization
has direct dependecy on Newtonsoft.Json
.
- Take your discriminated union and annotate it with
JsonConvert
attribute, givingOneOfJsonConverter<T>
as an argument (whereT
is your discriminated union)
NOTE: OneOf
class depends on the original OneOf
package version
OneOf
version2.x.x
(withoutGenerateOneOf
support)
[JsonConverter(typeof(OneOfJsonConverter<Status>))]
public class Status : OneOfBase<Idle, Running, Completed> {
public Status(Idle idle) : base(0, idle) {}
public Status(Running running) : base(1, null, running) {}
public Status(Completed completed) : base(2, null, null, completed) {}
public static implicit operator Status(Idle value) => value == null? null : new Status(value);
public static implicit operator Status(Running value) => value == null? null : new Status(value);
public static implicit operator Status(Completed value) => value == null? null : new Status(value);
}
OneOf
version3.x.x
(supportingGenerateOneOf
based on Source Generators)
[JsonConverter(typeof(OneOfJsonConverter<Status>))]
[GenerateOneOf]
public partial class Status : OneOfBase<Idle, Running, Completed> {
public Status(Idle idle) : base(idle) {}
public Status(Running running) : base(running) {}
public Status(Completed completed) : base(completed) {}
}
- Take all cases of your discriminated union and inherit
OneOfCase
marker class
public class Idle : OneOfCase {}
public class Running : OneOfCase
{
public DateTime StartedAt { get; }
public Running(DateTime startedAt) {
StartedAt = startedAt;
}
}
public class Completed : OneOfCase
{
public DateTime CompletedAt { get; }
public Running(DateTime completedAt) {
CompletedAt = completedAt;
}
}
- Serialize!
Status status = new Completed(DateTime.Now);
Console.WriteLine(JsonConvert.SerializeObject(status));
// output:
// {\r\n \"CompletedAt\": \"2020-11-17T21:29:52.0664389+01:00\",\r\n \"Value\": \"Completed\"\r\n }