Skip to content

Instantly share code, notes, and snippets.

@mikaeldui
Last active January 15, 2022 01:03
Show Gist options
  • Save mikaeldui/db6b75863c7ecefb5c82efe2dcbb6aa8 to your computer and use it in GitHub Desktop.
Save mikaeldui/db6b75863c7ecefb5c82efe2dcbb6aa8 to your computer and use it in GitHub Desktop.
Deserialize ReadOnlyCollection with System.Text.Json
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Reflection;
using System.Text;
namespace System.Text.Json.Serialization
{
public class JsonIReadOnlyCollectionConverter : JsonConverterFactory
{
public override bool CanConvert(Type typeToConvert)
{
if (typeToConvert.IsArray)
return false;
if (!typeToConvert.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IReadOnlyCollection<>)))
return false;
if ((typeToConvert.IsGenericType && typeToConvert.GetGenericTypeDefinition() != typeof(ReadOnlyCollection<>)) &&
!typeof(ReadOnlyCollection<>).IsSubclassOfRawGeneric(typeToConvert))
return false;
return true;
}
public override JsonConverter? CreateConverter(Type typeToConvert, JsonSerializerOptions options)
{
Type keyType = typeToConvert.GetGenericArguments()[0];
JsonConverter converter = (JsonConverter)Activator.CreateInstance(
typeof(IReadOnlyCollectionConverterInner<>).MakeGenericType(keyType),
BindingFlags.Instance | BindingFlags.Public,
binder: null, args: null, culture: null);
return converter;
}
private class IReadOnlyCollectionConverterInner<TValue> :
JsonConverter<IReadOnlyCollection<TValue>>
where TValue : notnull
{
public override IReadOnlyCollection<TValue> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var array = JsonSerializer.Deserialize<TValue[]>(ref reader, options: options);
return (IReadOnlyCollection<TValue>)Activator.CreateInstance(
typeToConvert,
BindingFlags.Instance | BindingFlags.Public,
binder: null,
#pragma warning disable CS8601 // Possible null reference assignment.
args: new object[] { array },
#pragma warning restore CS8601 // Possible null reference assignment.
culture: null);
}
public override void Write(Utf8JsonWriter writer, IReadOnlyCollection<TValue> dictionary, JsonSerializerOptions options) =>
JsonSerializer.Serialize(writer, dictionary, options);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment