Skip to content

Instantly share code, notes, and snippets.

@mikaeldui
Last active October 9, 2022 13:37
Show Gist options
  • Save mikaeldui/1383dda4147f461ac4154406c03cc180 to your computer and use it in GitHub Desktop.
Save mikaeldui/1383dda4147f461ac4154406c03cc180 to your computer and use it in GitHub Desktop.
Deserialize ReadOnlyDictionary 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 JsonIReadOnlyDictionaryConverter : JsonConverterFactory
{
public override bool CanConvert(Type typeToConvert)
{
if (!typeToConvert.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IReadOnlyDictionary<,>)))
return false;
if ((typeToConvert.IsGenericType && typeToConvert.GetGenericTypeDefinition() != typeof(ReadOnlyDictionary<,>)) &&
!typeof(ReadOnlyDictionary<,>).IsSubclassOfRawGeneric(typeToConvert))
return false;
return true;
}
public override JsonConverter? CreateConverter(Type typeToConvert, JsonSerializerOptions options)
{
Type keyType = typeToConvert.GetGenericArguments()[0];
Type valueType = typeToConvert.GetGenericArguments()[1];
JsonConverter converter = (JsonConverter)Activator.CreateInstance(
typeof(IReadOnlyDictionaryConverterInner<,>).MakeGenericType(keyType, valueType),
BindingFlags.Instance | BindingFlags.Public,
binder: null, args: null, culture: null);
return converter;
}
private class IReadOnlyDictionaryConverterInner<TKey, TValue> :
JsonConverter<IReadOnlyDictionary<TKey, TValue>>
where TKey : notnull
{
public override IReadOnlyDictionary<TKey, TValue> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var dictionary = JsonSerializer.Deserialize<Dictionary<TKey, TValue>>(ref reader, options: options);
return (IReadOnlyDictionary<TKey, TValue>)Activator.CreateInstance(
typeToConvert,
BindingFlags.Instance | BindingFlags.Public,
binder: null,
#pragma warning disable CS8601 // Possible null reference assignment.
args: new object[] { dictionary },
#pragma warning restore CS8601 // Possible null reference assignment.
culture: null);
}
public override void Write(Utf8JsonWriter writer, IReadOnlyDictionary<TKey, TValue> dictionary, JsonSerializerOptions options) =>
JsonSerializer.Serialize(writer, dictionary, options);
}
}
}
@menees
Copy link

menees commented Oct 9, 2022

There's a newer revision of this converter at https://stackoverflow.com/a/70813056/1882616 along with some discussion of how to use it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment