using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Text.Json; using System.Text.Json.Serialization; using PolymorphicDeSerialization.Models; namespace PolymorphicDeSerialization.CustomConverter { using System.Text.Json.Serialization; public class HI1ObjectConverter : JsonConverter { public override HI1Object Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { // Grab the type discriminator and use it to deserialise // to the correct derived type (without any error checking, because this is just a PoC). var jdoc = JsonDocument.ParseValue(ref reader); // Establish the correct type JsonElement typeVal; if (!jdoc.RootElement.TryGetProperty("xsiType", out typeVal)) throw new Exception("Couldn't get type of HI1Object"); Type? t = Type.GetType(typeVal.ToString()); if (t == null) throw new Exception($"Can't get type for {typeVal.ToString()}"); if (!t.IsAssignableTo(typeof(HI1Object))) throw new Exception($"Can't deserialize {t.Name} as not assignable to HI1Object"); // Make sure this converter isn't in the converters list, or // else this function will be called in an infinite recursion var dummyOptions = new JsonSerializerOptions(options); dummyOptions.Converters.Clear(); // Deserialize in to the correct type return (HI1Object)jdoc.Deserialize(t, dummyOptions); } public override void Write(Utf8JsonWriter writer, HI1Object hi1Object, JsonSerializerOptions options) { // This forces JsonSerializer to call GetType on the instance of // HI1Object and serialise it as the appropriate derived type // If we wanted to restrict this to specific known subtypes, we could do so JsonSerializer.Serialize(writer, hi1Object, options); } } }