-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add JSON Serialization for Elsa expression (#5490)
* Add JSON Serialization for Elsa expression Extended the expression serialization. Added new classes ExpressionJsonConverter and ExpressionJsonConverterFactory implementing serialization of expression objects. Also, made respective changes in different serializers and related files for seamless integration. * Fix XML comments * Set initial builder Id in ClrWorkflowProvider This commit involves a modification in ClrWorkflowProvider.cs where an Id was set for the builder. The Id was set with the format `workflowBuilderType.Name`:1.0, providing a deterministic identifier for each builder instance. * Add MysteriousPondWorkflow and associated HTTP endpoints A new workflow, MysteriousPondWorkflow, has been introduced along with HTTP endpoints to interact with it. The workflow simulates throwing an arbitrary amount of rupees into a mysterious pond and getting a luck prediction for the day based on the amount. An integration of this workflow is registered in the main Program.cs file, and the necessary directories to handle this workflow have been added to relevant project files.
- Loading branch information
1 parent
038d29b
commit 100ece8
Showing
15 changed files
with
252 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
56 changes: 56 additions & 0 deletions
56
samples/aspnet/Elsa.Samples.AspNet.WorkflowServer/Workflows/MysteriousPondWorkflow.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
using System.Net.Mime; | ||
using Elsa.Expressions.Models; | ||
using Elsa.Http; | ||
using Elsa.Workflows; | ||
using Elsa.Workflows.Activities; | ||
using Elsa.Workflows.Contracts; | ||
|
||
namespace Elsa.Samples.AspNet.WorkflowServer.Workflows; | ||
|
||
/// <summary> | ||
/// Represents a mysterious pond workflow. | ||
/// </summary> | ||
public class MysteriousPondWorkflow : WorkflowBase | ||
{ | ||
protected override void Build(IWorkflowBuilder builder) | ||
{ | ||
var investment = builder.WithVariable<Investment>(); | ||
|
||
builder.Root = new Sequence | ||
{ | ||
Activities = | ||
{ | ||
new HttpEndpoint | ||
{ | ||
Path = new("mysterious_pond"), | ||
SupportedMethods = new([HttpMethod.Post.Method]), | ||
ParsedContent = new(investment), | ||
CanStartWorkflow = true | ||
}, | ||
new WriteLine(context => $"Received {GetRupees(context)} rupees"), | ||
new Switch | ||
{ | ||
Cases = | ||
{ | ||
new SwitchCase("Great Luck", context => GetRupees(context) >= 1000, WriteHttpResponse("For today, you will have great luck.")), | ||
new SwitchCase("Good Luck", context => GetRupees(context) >= 500, WriteHttpResponse("For today, you will have good luck.")), | ||
new SwitchCase("A Little Luck", context => GetRupees(context) >= 250, WriteHttpResponse("For today, you will have a little luck.")), | ||
new SwitchCase("Bad Luck", context => GetRupees(context) < 250, WriteHttpResponse("For today, you will have bad luck.")), | ||
|
||
} | ||
} | ||
} | ||
}; | ||
return; | ||
|
||
int GetRupees(ExpressionExecutionContext context) => investment.Get(context)!.Rupees; | ||
} | ||
|
||
private static WriteHttpResponse WriteHttpResponse(string message) => new() | ||
{ | ||
Content = new(message), | ||
ContentType = new(MediaTypeNames.Text.Plain), | ||
}; | ||
|
||
private record Investment(int Rupees); | ||
}; |
31 changes: 31 additions & 0 deletions
31
samples/aspnet/Elsa.Samples.AspNet.WorkflowServer/mysterious_pond.http
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
### POST 1000 rupees to the mysterious pond. | ||
POST https://localhost:5001/workflows/mysterious_pond | ||
Content-Type: application/json | ||
|
||
{ | ||
"rupees": 1000 | ||
} | ||
|
||
### POST 500 rupees to the mysterious pond. | ||
POST https://localhost:5001/workflows/mysterious_pond | ||
Content-Type: application/json | ||
|
||
{ | ||
"rupees": 500 | ||
} | ||
|
||
### POST 250 rupees to the mysterious pond. | ||
POST https://localhost:5001/workflows/mysterious_pond | ||
Content-Type: application/json | ||
|
||
{ | ||
"rupees": 250 | ||
} | ||
|
||
### POST 100 rupees to the mysterious pond. | ||
POST https://localhost:5001/workflows/mysterious_pond | ||
Content-Type: application/json | ||
|
||
{ | ||
"rupees": 100 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -59,6 +59,7 @@ | |
|
||
<ItemGroup> | ||
<Folder Include="App_Data\"/> | ||
<Folder Include="Workflows\" /> | ||
</ItemGroup> | ||
|
||
</Project> |
31 changes: 31 additions & 0 deletions
31
src/modules/Elsa.Expressions/Extensions/JsonElementExtensions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
using System.Text.Json; | ||
|
||
// ReSharper disable once CheckNamespace | ||
namespace Elsa.Extensions; | ||
|
||
/// <summary> | ||
/// Parses a <see cref="JsonElement"/> into a .NET object. | ||
/// </summary> | ||
public static class JsonElementExtensions | ||
{ | ||
/// <summary> | ||
/// Parses a <see cref="JsonElement"/> into a .NET object. | ||
/// </summary> | ||
/// <param name="jsonElement">The JSON element to parse.</param> | ||
/// <returns>The parsed object.</returns> | ||
public static object? GetValue(this JsonElement jsonElement) | ||
{ | ||
return jsonElement.ValueKind switch | ||
{ | ||
JsonValueKind.String => jsonElement.GetString(), | ||
JsonValueKind.Number => jsonElement.GetDecimal(), | ||
JsonValueKind.True => true, | ||
JsonValueKind.False => false, | ||
JsonValueKind.Undefined => null, | ||
JsonValueKind.Null => null, | ||
JsonValueKind.Object => jsonElement.GetRawText(), | ||
JsonValueKind.Array => jsonElement.GetRawText(), | ||
_ => jsonElement.GetRawText() | ||
}; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
74 changes: 74 additions & 0 deletions
74
src/modules/Elsa.Workflows.Core/Serialization/Converters/ExpressionJsonConverter.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
using System.Text.Json; | ||
using System.Text.Json.Serialization; | ||
using Elsa.Expressions.Contracts; | ||
using Elsa.Expressions.Models; | ||
using Elsa.Workflows.Models; | ||
|
||
namespace Elsa.Workflows.Serialization.Converters; | ||
|
||
/// <summary> | ||
/// Serializes <see cref="Expression"/> objects. | ||
/// </summary> | ||
public class ExpressionJsonConverter : JsonConverter<Expression> | ||
{ | ||
private readonly IExpressionDescriptorRegistry _expressionDescriptorRegistry; | ||
|
||
/// <inheritdoc /> | ||
public ExpressionJsonConverter(IExpressionDescriptorRegistry expressionDescriptorRegistry) | ||
{ | ||
_expressionDescriptorRegistry = expressionDescriptorRegistry; | ||
} | ||
|
||
/// <inheritdoc /> | ||
public override bool CanConvert(Type typeToConvert) => typeof(Input).IsAssignableFrom(typeToConvert); | ||
|
||
/// <inheritdoc /> | ||
public override Expression Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) | ||
{ | ||
if (!JsonDocument.TryParseValue(ref reader, out var doc)) | ||
return default!; | ||
|
||
var expressionElement = doc.RootElement; | ||
var expressionTypeNameElement = expressionElement.TryGetProperty("type", out var expressionTypeNameElementValue) ? expressionTypeNameElementValue : default; | ||
var expressionTypeName = expressionTypeNameElement.ValueKind != JsonValueKind.Undefined ? expressionTypeNameElement.GetString() ?? "Literal" : default; | ||
var expressionDescriptor = expressionTypeName != null ? _expressionDescriptorRegistry.Find(expressionTypeName) : default; | ||
var memoryBlockReference = expressionDescriptor?.MemoryBlockReferenceFactory?.Invoke(); | ||
|
||
if (memoryBlockReference == null) | ||
return default!; | ||
|
||
var memoryBlockType = memoryBlockReference.GetType(); | ||
var context = new ExpressionSerializationContext(expressionTypeName!, expressionElement, options, memoryBlockType); | ||
var expression = expressionDescriptor!.Deserialize(context); | ||
|
||
return expression; | ||
} | ||
|
||
/// <inheritdoc /> | ||
public override void Write(Utf8JsonWriter writer, Expression value, JsonSerializerOptions options) | ||
{ | ||
var expression = value; | ||
|
||
if(expression == null) | ||
{ | ||
writer.WriteNullValue(); | ||
return; | ||
} | ||
|
||
var expressionType = expression.Type; | ||
var expressionDescriptor = expressionType != null ? _expressionDescriptorRegistry.Find(expressionType) : null; | ||
|
||
if (expressionDescriptor == null) | ||
throw new JsonException($"Could not find an expression descriptor for expression type '{expressionType}'."); | ||
|
||
var expressionValue = expressionDescriptor.IsSerializable ? expression.Value : null; | ||
|
||
var model = new | ||
{ | ||
Type = expressionType, | ||
Value = expressionValue | ||
}; | ||
|
||
JsonSerializer.Serialize(writer, model, options); | ||
} | ||
} |
29 changes: 29 additions & 0 deletions
29
src/modules/Elsa.Workflows.Core/Serialization/Converters/ExpressionJsonConverterFactory.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
using System.Text.Json; | ||
using System.Text.Json.Serialization; | ||
using Elsa.Expressions.Contracts; | ||
using Elsa.Expressions.Models; | ||
|
||
namespace Elsa.Workflows.Serialization.Converters; | ||
|
||
/// <summary> | ||
/// A JSON converter factory that creates <see cref="ExpressionJsonConverter"/> instances. | ||
/// </summary> | ||
public class ExpressionJsonConverterFactory : JsonConverterFactory | ||
{ | ||
private readonly IExpressionDescriptorRegistry _expressionDescriptorRegistry; | ||
|
||
/// <inheritdoc /> | ||
public ExpressionJsonConverterFactory(IExpressionDescriptorRegistry expressionDescriptorRegistry) | ||
{ | ||
_expressionDescriptorRegistry = expressionDescriptorRegistry; | ||
} | ||
|
||
/// <inheritdoc /> | ||
public override bool CanConvert(Type typeToConvert) => typeof(Expression).IsAssignableFrom(typeToConvert); | ||
|
||
/// <inheritdoc /> | ||
public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) | ||
{ | ||
return new ExpressionJsonConverter(_expressionDescriptorRegistry); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters