save progress
This commit is contained in:
@@ -0,0 +1,143 @@
|
||||
// <copyright file="FacetSealJsonConverter.cs" company="StellaOps">
|
||||
// Copyright (c) StellaOps. Licensed under AGPL-3.0-or-later.
|
||||
// </copyright>
|
||||
|
||||
using System.Collections.Immutable;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace StellaOps.Facet.Serialization;
|
||||
|
||||
/// <summary>
|
||||
/// JSON serialization options for facet seals.
|
||||
/// </summary>
|
||||
public static class FacetJsonOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the default JSON serializer options for facet seals.
|
||||
/// </summary>
|
||||
public static JsonSerializerOptions Default { get; } = CreateOptions();
|
||||
|
||||
/// <summary>
|
||||
/// Gets options for compact serialization (no indentation).
|
||||
/// </summary>
|
||||
public static JsonSerializerOptions Compact { get; } = CreateOptions(writeIndented: false);
|
||||
|
||||
/// <summary>
|
||||
/// Gets options for pretty-printed serialization.
|
||||
/// </summary>
|
||||
public static JsonSerializerOptions Pretty { get; } = CreateOptions(writeIndented: true);
|
||||
|
||||
private static JsonSerializerOptions CreateOptions(bool writeIndented = false)
|
||||
{
|
||||
var options = new JsonSerializerOptions
|
||||
{
|
||||
WriteIndented = writeIndented,
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
|
||||
PropertyNameCaseInsensitive = true
|
||||
};
|
||||
|
||||
options.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase));
|
||||
options.Converters.Add(new ImmutableArrayConverterFactory());
|
||||
options.Converters.Add(new ImmutableDictionaryConverterFactory());
|
||||
|
||||
return options;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converter factory for ImmutableArray{T}.
|
||||
/// </summary>
|
||||
internal sealed class ImmutableArrayConverterFactory : JsonConverterFactory
|
||||
{
|
||||
public override bool CanConvert(Type typeToConvert)
|
||||
{
|
||||
return typeToConvert.IsGenericType &&
|
||||
typeToConvert.GetGenericTypeDefinition() == typeof(ImmutableArray<>);
|
||||
}
|
||||
|
||||
public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
var elementType = typeToConvert.GetGenericArguments()[0];
|
||||
var converterType = typeof(ImmutableArrayConverter<>).MakeGenericType(elementType);
|
||||
return (JsonConverter)Activator.CreateInstance(converterType)!;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converter for ImmutableArray{T}.
|
||||
/// </summary>
|
||||
internal sealed class ImmutableArrayConverter<T> : JsonConverter<ImmutableArray<T>>
|
||||
{
|
||||
public override ImmutableArray<T> Read(
|
||||
ref Utf8JsonReader reader,
|
||||
Type typeToConvert,
|
||||
JsonSerializerOptions options)
|
||||
{
|
||||
if (reader.TokenType == JsonTokenType.Null)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
var list = JsonSerializer.Deserialize<List<T>>(ref reader, options);
|
||||
return list is null ? [] : [.. list];
|
||||
}
|
||||
|
||||
public override void Write(
|
||||
Utf8JsonWriter writer,
|
||||
ImmutableArray<T> value,
|
||||
JsonSerializerOptions options)
|
||||
{
|
||||
JsonSerializer.Serialize(writer, value.AsEnumerable(), options);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converter factory for ImmutableDictionary{TKey,TValue}.
|
||||
/// </summary>
|
||||
internal sealed class ImmutableDictionaryConverterFactory : JsonConverterFactory
|
||||
{
|
||||
public override bool CanConvert(Type typeToConvert)
|
||||
{
|
||||
return typeToConvert.IsGenericType &&
|
||||
typeToConvert.GetGenericTypeDefinition() == typeof(ImmutableDictionary<,>);
|
||||
}
|
||||
|
||||
public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
var keyType = typeToConvert.GetGenericArguments()[0];
|
||||
var valueType = typeToConvert.GetGenericArguments()[1];
|
||||
var converterType = typeof(ImmutableDictionaryConverter<,>).MakeGenericType(keyType, valueType);
|
||||
return (JsonConverter)Activator.CreateInstance(converterType)!;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converter for ImmutableDictionary{TKey,TValue}.
|
||||
/// </summary>
|
||||
internal sealed class ImmutableDictionaryConverter<TKey, TValue> : JsonConverter<ImmutableDictionary<TKey, TValue>>
|
||||
where TKey : notnull
|
||||
{
|
||||
public override ImmutableDictionary<TKey, TValue>? Read(
|
||||
ref Utf8JsonReader reader,
|
||||
Type typeToConvert,
|
||||
JsonSerializerOptions options)
|
||||
{
|
||||
if (reader.TokenType == JsonTokenType.Null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var dict = JsonSerializer.Deserialize<Dictionary<TKey, TValue>>(ref reader, options);
|
||||
return dict?.ToImmutableDictionary();
|
||||
}
|
||||
|
||||
public override void Write(
|
||||
Utf8JsonWriter writer,
|
||||
ImmutableDictionary<TKey, TValue> value,
|
||||
JsonSerializerOptions options)
|
||||
{
|
||||
JsonSerializer.Serialize(writer, value.AsEnumerable().ToDictionary(kv => kv.Key, kv => kv.Value), options);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user