< Summary

Information
Class: Elsa.Workflows.Serialization.Serializers.JsonActivitySerializer
Assembly: Elsa.Workflows.Core
File(s): /home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Workflows.Core/Serialization/Serializers/JsonActivitySerializer.cs
Line coverage
95%
Covered lines: 42
Uncovered lines: 2
Coverable lines: 44
Total lines: 99
Line coverage: 95.4%
Branch coverage
92%
Covered branches: 24
Total branches: 26
Branch coverage: 92.3%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
Serialize(...)100%1616100%
ValidatePropertyNames(...)75%8885.71%
Serialize(...)100%22100%
Deserialize(...)100%11100%
Deserialize(...)100%210%
Deserialize(...)100%11100%
AddConverters(...)100%11100%

File(s)

/home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Workflows.Core/Serialization/Serializers/JsonActivitySerializer.cs

#LineLine coverage
 1using System.Text;
 2using System.Text.Json;
 3using System.Text.Json.Serialization.Metadata;
 4using Elsa.Common.Serialization;
 5using Elsa.Workflows.Serialization.Converters;
 6using Elsa.Workflows.Serialization.Helpers;
 7using Microsoft.Extensions.DependencyInjection;
 8
 9namespace Elsa.Workflows.Serialization.Serializers;
 10
 11/// <inheritdoc cref="IActivitySerializer" />
 14312public class JsonActivitySerializer(IServiceProvider serviceProvider) : ConfigurableSerializer(serviceProvider), IActivi
 13{
 14    /// <inheritdoc />
 15    public string Serialize(IActivity activity)
 16    {
 287117        var options = GetOptionsInternal();
 287118        var descriptor = ServiceProvider.GetRequiredService<IActivityRegistry>().Find(activity.Type, activity.Version);
 498619        if (descriptor is null || !descriptor.Inputs.Any(input => input.IsSynthetic) && !descriptor.Outputs.Any(output =
 20        {
 285821            return JsonSerializer.Serialize(activity, activity.GetType(), options);
 22        }
 23
 24        // Keep normal CLR properties on System.Text.Json's metadata-aware path.
 25        // Only synthetic descriptor properties need the activity-specific writer.
 1326        options = new JsonSerializerOptions(options);
 1327        options = descriptor.ConfigureSerializerOptions?.Invoke(options) ?? options;
 1328        var serialized = JsonSerializer.SerializeToElement(activity, activity.GetType(), options);
 29        // A custom converter owns the complete representation, including synthetic fields.
 1330        if (options.GetTypeInfo(activity.GetType()).Kind != JsonTypeInfoKind.Object)
 31        {
 132            ValidatePropertyNames(serialized, options);
 133            return serialized.GetRawText();
 34        }
 1235        using var stream = new MemoryStream();
 1236        using (var writer = new Utf8JsonWriter(stream, new JsonWriterOptions { Indented = options.WriteIndented, Encoder
 37        {
 1238            writer.WriteStartObject();
 23839            foreach (var property in serialized.EnumerateObject())
 40            {
 10741                property.WriteTo(writer);
 42            }
 1243            ServiceProvider.GetRequiredService<SyntheticPropertiesWriter>().WriteSyntheticProperties(writer, activity, d
 1244            writer.WriteEndObject();
 1245        }
 1246        var json = Encoding.UTF8.GetString(stream.ToArray());
 1247        using var document = JsonDocument.Parse(json, new JsonDocumentOptions { MaxDepth = options.MaxDepth });
 1248        ValidatePropertyNames(document.RootElement, options);
 849        return json;
 850    }
 51
 52    private static void ValidatePropertyNames(JsonElement element, JsonSerializerOptions options)
 53    {
 1354        if (element.ValueKind != JsonValueKind.Object)
 55        {
 056            throw new JsonException("An activity must serialize to a JSON object.");
 57        }
 58
 1359        var names = new HashSet<string>(options.PropertyNameCaseInsensitive ? StringComparer.OrdinalIgnoreCase : StringC
 29660        foreach (var property in element.EnumerateObject())
 61        {
 13762            if (!names.Add(property.Name))
 63            {
 464                throw new JsonException($"Activity serialization contains the duplicate property '{property.Name}'.");
 65            }
 66        }
 967    }
 68
 69    /// <inheritdoc />
 70    public string Serialize(object value)
 71    {
 372        if (value is IActivity activity)
 73        {
 274            return Serialize(activity);
 75        }
 76
 177        var options = GetOptionsInternal();
 178        return JsonSerializer.Serialize(value, options);
 79    }
 80
 81    /// <inheritdoc />
 89482    public IActivity Deserialize(string serializedActivity) => JsonSerializer.Deserialize<IActivity>(serializedActivity,
 83
 84    /// <inheritdoc />
 085    public object Deserialize(string serializedValue, Type type) => JsonSerializer.Deserialize(serializedValue, type, Ge
 86
 87    /// <inheritdoc />
 93688    public T Deserialize<T>(string serializedValue) => JsonSerializer.Deserialize<T>(serializedValue, GetOptions())!;
 89
 90    /// <inheritdoc />
 91    protected override void AddConverters(JsonSerializerOptions options)
 92    {
 287293        options.Converters.Add(CreateInstance<TypeJsonConverter>());
 287294        options.Converters.Add(CreateInstance<InputJsonConverterFactory>());
 287295        options.Converters.Add(CreateInstance<OutputJsonConverterFactory>());
 287296        options.Converters.Add(CreateInstance<ExpressionJsonConverterFactory>());
 287297        options.Converters.Add(CreateInstance<FuncExpressionValueConverter>());
 287298    }
 99}