using System; using System.Collections.Generic; using System.Reflection; using System.Text.Json; using System.Text.Json.Serialization; namespace CC_Functions.AspNet { /// /// Provides serializing dictionary with Guid keys /// public class DictionaryGuidConverter : JsonConverterFactory { /// public override bool CanConvert(Type typeToConvert) { if (!typeToConvert.IsGenericType) { return false; } if (typeToConvert.GetGenericTypeDefinition() != typeof(Dictionary<,>)) { return false; } return typeToConvert.GetGenericArguments()[0] == typeof(Guid); } /// public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) { Type valueType = typeToConvert.GetGenericArguments()[1]; JsonConverter converter = (JsonConverter)Activator.CreateInstance( typeof(DictionaryGuidConverterInner<>).MakeGenericType(valueType), BindingFlags.Instance | BindingFlags.Public, null, new object[] { options }, null); return converter; } private class DictionaryGuidConverterInner : JsonConverter> { private readonly JsonConverter _valueConverter; private Type _valueType; public DictionaryGuidConverterInner(JsonSerializerOptions options) { // For performance, use the existing converter if available. _valueConverter = (JsonConverter)options .GetConverter(typeof(TValue)); // Cache the key and value types. _valueType = typeof(TValue); } public override Dictionary Read( ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType != JsonTokenType.StartObject) { throw new JsonException(); } Dictionary dictionary = new(); while (reader.Read()) { if (reader.TokenType == JsonTokenType.EndObject) { return dictionary; } // Get the key. if (reader.TokenType != JsonTokenType.PropertyName) { throw new JsonException(); } string propertyName = reader.GetString(); // For performance, parse with ignoreCase:false first. if (!Guid.TryParse(propertyName, out Guid key)) { throw new JsonException( $"Unable to convert \"{propertyName}\" to Guid."); } // Get the value. TValue v; if (_valueConverter != null) { reader.Read(); v = _valueConverter.Read(ref reader, _valueType, options); } else { v = JsonSerializer.Deserialize(ref reader, options); } // Add to dictionary. dictionary.Add(key, v); } throw new JsonException(); } public override void Write( Utf8JsonWriter writer, Dictionary dictionary, JsonSerializerOptions options) { writer.WriteStartObject(); foreach (KeyValuePair kvp in dictionary) { writer.WritePropertyName(kvp.Key.ToString()); if (_valueConverter != null) { _valueConverter.Write(writer, kvp.Value, options); } else { JsonSerializer.Serialize(writer, kvp.Value, options); } } writer.WriteEndObject(); } } } }