using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization.Metadata;
using System.Text.Unicode;
using Elsa.Common.Contracts;
using Elsa.Common.Converters;
using Microsoft.Extensions.DependencyInjection;
namespace Elsa.Common.Serialization;
///
/// A base class for configurable JSON serializers.
///
public abstract class ConfigurableSerializer
{
private JsonSerializerOptions? _options;
///
/// Initializes a new instance of the class.
///
protected ConfigurableSerializer(IServiceProvider serviceProvider)
{
ServiceProvider = serviceProvider;
}
///
/// Gets the service provider.
///
protected IServiceProvider ServiceProvider { get; }
///
/// Creates a new instance of with the configured options.
///
public virtual JsonSerializerOptions GetOptions()
{
if (_options != null)
return _options;
var options = CreateOptionsInternal();
ApplyOptions(options);
_options = options;
return options;
}
///
/// Creates a new instance of with the configured options.
///
public virtual void ApplyOptions(JsonSerializerOptions options)
{
Configure(options);
AddConverters(options);
RunConfigurators(options);
}
///
/// Creates a new instance of .
///
protected JsonSerializerOptions GetOptionsInternal()
{
var options = CreateOptionsInternal();
ApplyOptions(options);
_options = options;
return options;
}
///
/// Creates a new instance of .
///
private static JsonSerializerOptions CreateOptionsInternal()
{
var options = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
PropertyNameCaseInsensitive = true,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
Encoder = JavaScriptEncoder.Create(UnicodeRanges.All)
};
options.Converters.Add(new JsonStringEnumConverter());
options.Converters.Add(JsonMetadataServices.TimeSpanConverter);
options.Converters.Add(new IntegerJsonConverter());
options.Converters.Add(new DecimalJsonConverter());
return options;
}
///
/// Configures the object.
///
protected virtual void Configure(JsonSerializerOptions options)
{
}
///
/// Adds additional objects.
///
protected virtual void AddConverters(JsonSerializerOptions options)
{
}
///
/// Give external packages a chance to further configure the serializer options.
///
protected virtual void RunConfigurators(JsonSerializerOptions options)
{
var configurators = ServiceProvider.GetServices();
var modifiers = new List>();
foreach (var configurator in configurators)
{
configurator.Configure(options);
var modifiersToAdd = configurator.GetModifiers();
modifiers.AddRange(modifiersToAdd);
}
options.TypeInfoResolver = new ModifiableJsonTypeInfoResolver(modifiers);
}
///
/// Creates an instance of the specified type using the service provider.
///
protected T CreateInstance() => ActivatorUtilities.CreateInstance(ServiceProvider);
}