#nullable enable
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace MediaBrowser.Common.Json.Converters
{
///
/// Converter for Dictionaries without string key.
/// TODO This can be removed when System.Text.Json supports Dictionaries with non-string keys.
///
/// Type of key.
/// Type of value.
internal sealed class JsonNonStringKeyDictionaryConverter : JsonConverter>
{
///
/// Read JSON.
///
/// The Utf8JsonReader.
/// The type to convert.
/// The json serializer options.
/// Typed dictionary.
///
public override IDictionary Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var convertedType = typeof(Dictionary<,>).MakeGenericType(typeof(string), typeToConvert.GenericTypeArguments[1]);
var value = JsonSerializer.Deserialize(ref reader, convertedType, options);
var instance = (Dictionary)Activator.CreateInstance(
typeToConvert,
BindingFlags.Instance | BindingFlags.Public,
null,
null,
CultureInfo.CurrentCulture);
var enumerator = (IEnumerator)convertedType.GetMethod("GetEnumerator")!.Invoke(value, null);
var parse = typeof(TKey).GetMethod(
"Parse",
0,
BindingFlags.Public | BindingFlags.Static,
null,
CallingConventions.Any,
new[] { typeof(string) },
null);
if (parse == null)
{
throw new NotSupportedException($"{typeof(TKey)} as TKey in IDictionary is not supported.");
}
while (enumerator.MoveNext())
{
var element = (KeyValuePair)enumerator.Current;
instance.Add((TKey)parse.Invoke(null, new[] { (object?) element.Key }), element.Value);
}
return instance;
}
///
/// Write dictionary as Json.
///
/// The Utf8JsonWriter.
/// The dictionary value.
/// The Json serializer options.
public override void Write(Utf8JsonWriter writer, IDictionary value, JsonSerializerOptions options)
{
var convertedDictionary = new Dictionary(value.Count);
foreach (var (k, v) in value)
{
convertedDictionary[k?.ToString()] = v;
}
JsonSerializer.Serialize(writer, convertedDictionary, options);
}
}
}