#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. /// Not supported. 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) { if (k != null) { convertedDictionary[k.ToString()] = v; } } JsonSerializer.Serialize(writer, convertedDictionary, options); } } }