Created
August 1, 2023 23:23
-
-
Save SQL-MisterMagoo/0be37110225b977f0aa2023b39aa8b8d to your computer and use it in GitHub Desktop.
Why dotnet, why? Or how to deserialize with a collection of interface
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Text.Json; | |
using System.Text.Json.Serialization; | |
/* Setup */ | |
Thing[] someThings = { new("1"), new("2") }; | |
var myThings = new Things(someThings); | |
/* Staying in dotnet - this all works as expected */ | |
var asInterfaces = myThings as IThings; | |
var asThings = asInterfaces as Things; | |
var castInterfaces2 = (IThings)asThings; | |
var castThings2 = (Things)asInterfaces; | |
Console.WriteLine("dotnet world: "+JsonSerializer.Serialize(castThings2)); | |
/* Round trip JSON De-Serialization fails without the converter | |
* but doesn't say exactly why */ | |
var json = JsonSerializer.Serialize(myThings); | |
Things? newThings = JsonSerializer.Deserialize<Things>( | |
json, | |
new JsonSerializerOptions(JsonSerializerDefaults.General) | |
{ | |
Converters = { new CollectionConverter<Thing, IThing>() } | |
} | |
); | |
/* serialize just to display */ | |
var json2 = JsonSerializer.Serialize(newThings); | |
Console.WriteLine("JSON world: "+json2); | |
Console.ReadLine(); | |
/* Interfaces */ | |
interface IThing{ string Id { get; } } | |
interface IThings{ IEnumerable<IThing> AllThings { get; } } | |
/* Implementation */ | |
class Thing(string id) : IThing { public string Id { get; } = id; } | |
class Things(IEnumerable<IThing> allThings) : IThings | |
{ | |
public IEnumerable<IThing> AllThings { get; } = allThings; | |
} | |
/* JsonConverter */ | |
public class CollectionConverter<T, U> : JsonConverter<IEnumerable<U>> where T : U | |
{ | |
public override IEnumerable<U>? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) | |
=> JsonSerializer.Deserialize<IEnumerable<T>>(ref reader, options)?.Cast<U>(); | |
public override void Write(Utf8JsonWriter writer, IEnumerable<U> value, JsonSerializerOptions options) | |
=> JsonSerializer.Serialize(writer, value.Cast<T>(), options); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment