HI1ObjectConverter.cs 2.09 KB
Newer Older
canterburym's avatar
canterburym committed
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<HI1Object>
    {
        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<object>(writer, hi1Object, options);
        }
    }
}