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();
}
}
}
}