138 lines
4.4 KiB
C#
138 lines
4.4 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();
|
||
|
|
||
|
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();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|