138 lines
4.5 KiB
C#
138 lines
4.5 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Reflection;
|
|
using System.Text.Json;
|
|
using System.Text.Json.Serialization;
|
|
|
|
namespace CC_Functions.AspNet
|
|
{
|
|
/// <summary>
|
|
/// Provides serializing dictionary with Guid keys
|
|
/// </summary>
|
|
public class DictionaryGuidConverter : JsonConverterFactory
|
|
{
|
|
/// <inheritdoc />
|
|
public override bool CanConvert(Type typeToConvert)
|
|
{
|
|
if (!typeToConvert.IsGenericType)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (typeToConvert.GetGenericTypeDefinition() != typeof(Dictionary<,>))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return typeToConvert.GetGenericArguments()[0] == typeof(Guid);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
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<TValue> : JsonConverter<Dictionary<Guid, TValue>>
|
|
{
|
|
private readonly JsonConverter<TValue> _valueConverter;
|
|
private Type _valueType;
|
|
|
|
public DictionaryGuidConverterInner(JsonSerializerOptions options)
|
|
{
|
|
// For performance, use the existing converter if available.
|
|
_valueConverter = (JsonConverter<TValue>)options
|
|
.GetConverter(typeof(TValue));
|
|
|
|
// Cache the key and value types.
|
|
_valueType = typeof(TValue);
|
|
}
|
|
|
|
public override Dictionary<Guid, TValue> Read(
|
|
ref Utf8JsonReader reader,
|
|
Type typeToConvert,
|
|
JsonSerializerOptions options)
|
|
{
|
|
if (reader.TokenType != JsonTokenType.StartObject)
|
|
{
|
|
throw new JsonException();
|
|
}
|
|
|
|
Dictionary<Guid, TValue> dictionary = new Dictionary<Guid, TValue>();
|
|
|
|
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<TValue>(ref reader, options);
|
|
}
|
|
|
|
// Add to dictionary.
|
|
dictionary.Add(key, v);
|
|
}
|
|
|
|
throw new JsonException();
|
|
}
|
|
|
|
public override void Write(
|
|
Utf8JsonWriter writer,
|
|
Dictionary<Guid, TValue> dictionary,
|
|
JsonSerializerOptions options)
|
|
{
|
|
writer.WriteStartObject();
|
|
|
|
foreach (KeyValuePair<Guid, TValue> 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();
|
|
}
|
|
}
|
|
}
|
|
} |