Commit 40503be4 authored by canterburym's avatar canterburym
Browse files

Messing with JsonConverters

parent ad7c7e02
Pipeline #12352 passed with stage
in 39 seconds
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);
}
}
}
......@@ -5,6 +5,12 @@
public string ObjectIdentifier { get; set; }
public int Generation { get; set; }
// This serves the same purpose as the "typeDiscriminator" field.
// I've called it xsiType because in OAS3 we can map the XSD xsiType
// field (which is essentially XML's type discriminator) directly to JSON.
// This just uses the .NET type name because it's just a demo and
// I'm too lazy to actually map to the correct Qnames here.
public string xsiType { get => this.GetType().ToString(); }
public void ToString()
{
Console.WriteLine(this.GetType().Name);
......
......@@ -2,6 +2,8 @@
using PolymorphicDeSerialization.Models;
using System.Text.Json;
using PolymorphicDeSerialization.CustomConverter;
// Make an LI Task Object
var lit = new LITaskObject
{
......@@ -26,13 +28,25 @@ PrintFooter();
// Scenario 3: Assign the derived type to a base type property of an object. This will result in loss of data when serialized.
PrintHeader("Now make an HI1Message. This has a property of type HI1Object as it can represent any HI1Object.", false);
PrintHeader("Only the HI1Object properties will be serialized. The fields in the derived type will be lost.");
//PrintHeader("Only the HI1Object properties will be serialized. The fields in the derived type will be lost.");
PrintHeader("Using a custom JSONConverter, we ensure that fields in the derived type are properly round-tripped.", false);
var hi1Message = new HI1Message
{
HI1Object = lit
};
var hi1MessageString = JsonSerializer.Serialize(hi1Message);
var newSerOptions = new JsonSerializerOptions()
{
WriteIndented = true,
Converters =
{
new HI1ObjectConverter()
}
};
var hi1MessageString = JsonSerializer.Serialize(hi1Message, newSerOptions);
Console.WriteLine(hi1MessageString);
HI1Message roundTrip = JsonSerializer.Deserialize<HI1Message>(hi1MessageString, newSerOptions);
Console.WriteLine($"Deserialized to {roundTrip.HI1Object.GetType().Name} with Target Identifier \"{(roundTrip.HI1Object as LITaskObject).TargetIdentifier}\"");
PrintFooter();
// Scenario 4: Create a custom serializer to handle derived types when serializing an object with properties of HI1Object and not the derived types.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment