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