Add TypeJsonConverter and enhance JSON serialization
Introduced a TypeJsonConverter to handle Type serialization and deserialization. Updated dependency injection and helper methods to support customized JSON serializer options, improving flexibility and configurability.
This commit is contained in:
parent
86826a89dc
commit
679a0515c8
56
src/clients/Elsa.Api.Client/Converters/TypeJsonConverter.cs
Normal file
56
src/clients/Elsa.Api.Client/Converters/TypeJsonConverter.cs
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using Elsa.Api.Client.Extensions;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace Elsa.Api.Client.Converters;
|
||||
|
||||
/// <summary>
|
||||
/// Converts <see cref="Type"/> objects to and from their assembly-qualified name.
|
||||
/// </summary>
|
||||
[UsedImplicitly]
|
||||
public class TypeJsonConverter : JsonConverter<Type>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override bool CanConvert(Type typeToConvert)
|
||||
{
|
||||
return typeToConvert == typeof(Type) || typeToConvert.FullName == "System.RuntimeType";
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Type? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
var typeName = reader.GetString()!;
|
||||
|
||||
// Handle collection types.
|
||||
if (typeName.EndsWith("[]"))
|
||||
{
|
||||
var elementTypeName = typeName[..^"[]".Length];
|
||||
var elementType = Type.GetType(elementTypeName)!;
|
||||
return typeof(List<>).MakeGenericType(elementType);
|
||||
}
|
||||
|
||||
return Type.GetType(typeName);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Write(Utf8JsonWriter writer, Type value, JsonSerializerOptions options)
|
||||
{
|
||||
// Handle collection types.
|
||||
if (value is { IsGenericType: true, GenericTypeArguments.Length: 1 })
|
||||
{
|
||||
var elementType = value.GenericTypeArguments.First();
|
||||
var typedEnumerable = typeof(IEnumerable<>).MakeGenericType(elementType);
|
||||
|
||||
if (typedEnumerable.IsAssignableFrom(value))
|
||||
{
|
||||
var elementTypeName = value.GetSimpleAssemblyQualifiedName();
|
||||
JsonSerializer.Serialize(writer, $"{elementTypeName}[]", options);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var typeName = value.GetSimpleAssemblyQualifiedName();
|
||||
JsonSerializer.Serialize(writer, typeName, options);
|
||||
}
|
||||
}
|
||||
|
|
@ -124,7 +124,7 @@ public static class DependencyInjectionExtensions
|
|||
/// <param name="httpClientBuilderOptions">An options object that can be used to configure the HTTP client builder.</param>
|
||||
public static IServiceCollection AddApi(this IServiceCollection services, Type apiType, ElsaClientBuilderOptions? httpClientBuilderOptions = default)
|
||||
{
|
||||
var builder = services.AddRefitClient(apiType, _ => CreateRefitSettings(), apiType.Name).ConfigureHttpClient(ConfigureElsaApiHttpClient);
|
||||
var builder = services.AddRefitClient(apiType, sp => CreateRefitSettings(sp, httpClientBuilderOptions?.ConfigureJsonSerializerOptions), apiType.Name).ConfigureHttpClient(ConfigureElsaApiHttpClient);
|
||||
httpClientBuilderOptions?.ConfigureHttpClientBuilder(builder);
|
||||
httpClientBuilderOptions?.ConfigureRetryPolicy?.Invoke(builder);
|
||||
return services;
|
||||
|
|
@ -139,7 +139,7 @@ public static class DependencyInjectionExtensions
|
|||
public static void AddApiWithoutRetryPolicy<T>(this IServiceCollection services, ElsaClientBuilderOptions? httpClientBuilderOptions = default) where T : class
|
||||
{
|
||||
var builder = services
|
||||
.AddRefitClient<T>(_ => CreateRefitSettings(), typeof(T).Name)
|
||||
.AddRefitClient<T>(sp => CreateRefitSettings(sp), typeof(T).Name)
|
||||
.ConfigureHttpClient(ConfigureElsaApiHttpClient);
|
||||
httpClientBuilderOptions?.ConfigureHttpClientBuilder(builder);
|
||||
}
|
||||
|
|
@ -156,7 +156,7 @@ public static class DependencyInjectionExtensions
|
|||
/// Creates an API client for the specified API type.
|
||||
public static T CreateApi<T>(this IServiceProvider serviceProvider, HttpClient httpClient) where T : class
|
||||
{
|
||||
return RestService.For<T>(httpClient, CreateRefitSettings());
|
||||
return RestService.For<T>(httpClient, CreateRefitSettings(serviceProvider));
|
||||
}
|
||||
|
||||
private static void ConfigureElsaApiHttpClient(IServiceProvider serviceProvider, HttpClient httpClient)
|
||||
|
|
|
|||
|
|
@ -10,17 +10,12 @@ namespace Elsa.Api.Client;
|
|||
/// </summary>
|
||||
public static class RefitSettingsHelper
|
||||
{
|
||||
private static JsonSerializerOptions? _jsonSerializerOptions;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="RefitSettings"/> instance configured for Elsa.
|
||||
/// </summary>
|
||||
public static RefitSettings CreateRefitSettings()
|
||||
public static RefitSettings CreateRefitSettings(IServiceProvider serviceProvider, Action<IServiceProvider, JsonSerializerOptions>? configureJsonSerializerOptions = null)
|
||||
{
|
||||
var settings = new RefitSettings
|
||||
{
|
||||
ContentSerializer = new SystemTextJsonContentSerializer(CreateJsonSerializerOptions())
|
||||
};
|
||||
var settings = new RefitSettings { ContentSerializer = new SystemTextJsonContentSerializer(CreateJsonSerializerOptions(serviceProvider, configureJsonSerializerOptions)) };
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
|
@ -28,11 +23,8 @@ public static class RefitSettingsHelper
|
|||
/// <summary>
|
||||
/// Creates a <see cref="JsonSerializerOptions"/> instance configured for Elsa.
|
||||
/// </summary>
|
||||
public static JsonSerializerOptions CreateJsonSerializerOptions()
|
||||
public static JsonSerializerOptions CreateJsonSerializerOptions(IServiceProvider serviceProvider, Action<IServiceProvider, JsonSerializerOptions>? configureJsonSerializerOptions = null)
|
||||
{
|
||||
if (_jsonSerializerOptions != null)
|
||||
return _jsonSerializerOptions;
|
||||
|
||||
var options = new JsonSerializerOptions
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||
|
|
@ -40,7 +32,10 @@ public static class RefitSettingsHelper
|
|||
|
||||
options.Converters.Add(new JsonStringEnumConverter());
|
||||
options.Converters.Add(new VersionOptionsJsonConverter());
|
||||
options.Converters.Add(new TypeJsonConverter());
|
||||
|
||||
return _jsonSerializerOptions = options;
|
||||
configureJsonSerializerOptions?.Invoke(serviceProvider, options);
|
||||
|
||||
return options;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
using System.Text.Json;
|
||||
using Elsa.Api.Client.HttpMessageHandlers;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Polly;
|
||||
|
|
@ -39,4 +40,9 @@ public class ElsaClientBuilderOptions
|
|||
/// Gets or sets a delegate that can be used to configure the retry policy.
|
||||
/// </summary>
|
||||
public Action<IHttpClientBuilder>? ConfigureRetryPolicy { get; set; } = builder => builder.AddTransientHttpErrorPolicy(p => p.WaitAndRetryAsync(3, attempt => TimeSpan.FromSeconds(Math.Pow(2, attempt))));
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a delegate that can be used to configure the JSON serializer options.
|
||||
/// </summary>
|
||||
public Action<IServiceProvider, JsonSerializerOptions>? ConfigureJsonSerializerOptions { get; set; }
|
||||
}
|
||||
|
|
@ -9,7 +9,7 @@ namespace Elsa.Workflows.Serialization.Converters;
|
|||
/// <summary>
|
||||
/// Serializes <see cref="Type"/> objects to a simple alias representing the type.
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
[UsedImplicitly]
|
||||
public class TypeJsonConverter : JsonConverter<Type>
|
||||
{
|
||||
private readonly IWellKnownTypeRegistry _wellKnownTypeRegistry;
|
||||
|
|
|
|||
Loading…
Reference in a new issue