From a0cda3830ccbe57650dcfe385032fb274a4e6816 Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Thu, 14 Mar 2024 09:59:22 +0100 Subject: [PATCH] Add DecimalJsonConverter and update usage Introduce a new DecimalJsonConverter class and refactor serialization setup. Renamed IntegerConverter to IntegerJsonConverter and updated its implementation to handle both number and string JSON tokens. Adjusted serializer options in ConfigurableSerializer and ObjectExpressionHandler accordingly. --- .../Converters/DecimalJsonConverter.cs | 32 +++++++++++++++++++ .../Converters/IntegerJsonConverter.cs} | 22 +++++++------ .../Serialization/ConfigurableSerializer.cs | 3 ++ .../Expressions/ObjectExpressionHandler.cs | 9 ++++-- 4 files changed, 55 insertions(+), 11 deletions(-) create mode 100644 src/modules/Elsa.Common/Converters/DecimalJsonConverter.cs rename src/modules/{Elsa.Workflows.Core/Serialization/Converters/IntegerConverter.cs => Elsa.Common/Converters/IntegerJsonConverter.cs} (50%) diff --git a/src/modules/Elsa.Common/Converters/DecimalJsonConverter.cs b/src/modules/Elsa.Common/Converters/DecimalJsonConverter.cs new file mode 100644 index 000000000..95b172545 --- /dev/null +++ b/src/modules/Elsa.Common/Converters/DecimalJsonConverter.cs @@ -0,0 +1,32 @@ +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Elsa.Common.Converters; + +/// +/// Converts decimals to and from JSON strings. +/// +public class DecimalJsonConverter : JsonConverter +{ + /// + public override decimal Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType == JsonTokenType.Number) + return reader.GetDecimal(); + + if (reader.TokenType == JsonTokenType.String) + { + var value = reader.GetString()!; + return decimal.Parse(value); + } + + throw new JsonException("Expected number or string."); + } + + /// + public override void Write(Utf8JsonWriter writer, decimal value, JsonSerializerOptions options) + { + // Write the decimal as a JSON number + writer.WriteNumberValue(value); + } +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Core/Serialization/Converters/IntegerConverter.cs b/src/modules/Elsa.Common/Converters/IntegerJsonConverter.cs similarity index 50% rename from src/modules/Elsa.Workflows.Core/Serialization/Converters/IntegerConverter.cs rename to src/modules/Elsa.Common/Converters/IntegerJsonConverter.cs index a39129003..8c2bbf5b7 100644 --- a/src/modules/Elsa.Workflows.Core/Serialization/Converters/IntegerConverter.cs +++ b/src/modules/Elsa.Common/Converters/IntegerJsonConverter.cs @@ -1,28 +1,32 @@ using System.Text.Json; using System.Text.Json.Serialization; -namespace Elsa.Workflows.Serialization.Converters; +namespace Elsa.Common.Converters; /// /// Converts integers to and from JSON strings. /// -public class IntegerConverter : JsonConverter +public class IntegerJsonConverter : JsonConverter { /// public override int Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - // Read the JSON string value and parse it as an integer - var value = reader.GetString()!; - var integer = int.Parse(value); - - // Return the parsed integer - return integer; + if (reader.TokenType == JsonTokenType.Number) + return reader.GetInt32(); + + if (reader.TokenType == JsonTokenType.String) + { + var value = reader.GetString()!; + return int.Parse(value); + } + + throw new JsonException("Expected number or string."); } /// public override void Write(Utf8JsonWriter writer, int value, JsonSerializerOptions options) { - // Write the integer as a JSON number + // Write the integer as a JSON number. writer.WriteNumberValue(value); } } \ No newline at end of file diff --git a/src/modules/Elsa.Common/Serialization/ConfigurableSerializer.cs b/src/modules/Elsa.Common/Serialization/ConfigurableSerializer.cs index fc5c2179d..ab7185eb3 100644 --- a/src/modules/Elsa.Common/Serialization/ConfigurableSerializer.cs +++ b/src/modules/Elsa.Common/Serialization/ConfigurableSerializer.cs @@ -4,6 +4,7 @@ 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; @@ -61,6 +62,8 @@ public abstract class ConfigurableSerializer options.Converters.Add(new JsonStringEnumConverter()); options.Converters.Add(JsonMetadataServices.TimeSpanConverter); + options.Converters.Add(new IntegerJsonConverter()); + options.Converters.Add(new DecimalJsonConverter()); return options; } diff --git a/src/modules/Elsa.Workflows.Core/Expressions/ObjectExpressionHandler.cs b/src/modules/Elsa.Workflows.Core/Expressions/ObjectExpressionHandler.cs index 83bbdbfc7..6f4877850 100644 --- a/src/modules/Elsa.Workflows.Core/Expressions/ObjectExpressionHandler.cs +++ b/src/modules/Elsa.Workflows.Core/Expressions/ObjectExpressionHandler.cs @@ -1,17 +1,21 @@ +using System.Diagnostics.CodeAnalysis; using System.Text.Json; +using Elsa.Common.Converters; using Elsa.Expressions.Contracts; using Elsa.Expressions.Helpers; using Elsa.Expressions.Models; -using Elsa.Workflows.Serialization.Converters; +using JetBrains.Annotations; namespace Elsa.Workflows.Expressions; /// /// Evaluates an object expression. /// +[UsedImplicitly] public class ObjectExpressionHandler : IExpressionHandler { /// + [RequiresUnreferencedCode("The type is not known at compile time.")] public ValueTask EvaluateAsync(Expression expression, Type returnType, ExpressionExecutionContext context, ExpressionEvaluatorOptions options) { var value = expression.Value.ConvertTo() ?? ""; @@ -20,7 +24,8 @@ public class ObjectExpressionHandler : IExpressionHandler return ValueTask.FromResult(default(object?)); var serializerOptions = new JsonSerializerOptions(); - serializerOptions.Converters.Add(new IntegerConverter()); + serializerOptions.Converters.Add(new IntegerJsonConverter()); + serializerOptions.Converters.Add(new DecimalJsonConverter()); var converterOptions = new ObjectConverterOptions(serializerOptions); var model = value.ConvertTo(returnType, converterOptions);