From 9f7609404d60402f7b11eceb9c80ee11b8357e5f Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 21 Apr 2026 22:08:56 +0000
Subject: [PATCH 1/2] Initial plan
From 18b4529f625a181b44de44949c986b1ca2fe0a73 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 21 Apr 2026 22:13:57 +0000
Subject: [PATCH 2/2] Add ToLower, Trim, ToDecimal operations and
AddJsonTransform DI helper
Agent-Logs-Url: https://github.com/mathieumack/JSLTSharp/sessions/50cd9ad1-7085-46df-b0f9-43faf863a6b7
Co-authored-by: mathieumack <12582537+mathieumack@users.noreply.github.com>
---
.../ToDecimalTransformTests.cs | 106 ++++++++++++++++++
.../ToLowerTransformTests.cs | 64 +++++++++++
.../TrimTransformTests.cs | 92 +++++++++++++++
.../ToDecimalTransformOperation.cs | 37 ++++++
.../ToLowerTransformationOperation.cs | 21 ++++
.../TrimTransformOperation.cs | 21 ++++
.../Extensions/JsonTransformExtensions.cs | 15 +++
7 files changed, 356 insertions(+)
create mode 100644 src/JSLTSharp.Tests/EmbededFunctions/ValueTransformations/ToDecimalTransformTests.cs
create mode 100644 src/JSLTSharp.Tests/EmbededFunctions/ValueTransformations/ToLowerTransformTests.cs
create mode 100644 src/JSLTSharp.Tests/EmbededFunctions/ValueTransformations/TrimTransformTests.cs
create mode 100644 src/JSLTSharp/JsonTransforms/EmbededFunctions/ValueTransformations/ToDecimalTransformOperation.cs
create mode 100644 src/JSLTSharp/JsonTransforms/EmbededFunctions/ValueTransformations/ToLowerTransformationOperation.cs
create mode 100644 src/JSLTSharp/JsonTransforms/EmbededFunctions/ValueTransformations/TrimTransformOperation.cs
diff --git a/src/JSLTSharp.Tests/EmbededFunctions/ValueTransformations/ToDecimalTransformTests.cs b/src/JSLTSharp.Tests/EmbededFunctions/ValueTransformations/ToDecimalTransformTests.cs
new file mode 100644
index 0000000..bf9e5cb
--- /dev/null
+++ b/src/JSLTSharp.Tests/EmbededFunctions/ValueTransformations/ToDecimalTransformTests.cs
@@ -0,0 +1,106 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace JSLTSharp.Tests.Transforms
+{
+ [TestClass]
+ public class ToDecimalTransformTests : BaseTestsClass
+ {
+ [TestMethod]
+ public void TestFloat_ToDecimal()
+ {
+ TestJsonTransformation(@"{
+ 'value': 13246.51
+ }",
+ @"{
+ 'result': '$.value->ToDecimal()'
+ }",
+ @"{
+ 'result': 13246.51
+ }");
+ }
+
+ [TestMethod]
+ public void TestInteger_ToDecimal()
+ {
+ TestJsonTransformation(@"{
+ 'value': 100
+ }",
+ @"{
+ 'result': '$.value->ToDecimal()'
+ }",
+ @"{
+ 'result': 100.0
+ }");
+ }
+
+ [TestMethod]
+ public void TestString_ValidNumber()
+ {
+ TestJsonTransformation(@"{
+ 'value': '42.5'
+ }",
+ @"{
+ 'result': '$.value->ToDecimal()'
+ }",
+ @"{
+ 'result': 42.5
+ }");
+ }
+
+ [TestMethod]
+ public void TestString_InvalidNumber()
+ {
+ TestJsonTransformation(@"{
+ 'value': 'notanumber'
+ }",
+ @"{
+ 'result': '$.value->ToDecimal()'
+ }",
+ @"{
+ 'result': null
+ }");
+ }
+
+ [TestMethod]
+ public void TestBoolean_True()
+ {
+ TestJsonTransformation(@"{
+ 'value': true
+ }",
+ @"{
+ 'result': '$.value->ToDecimal()'
+ }",
+ @"{
+ 'result': 1.0
+ }");
+ }
+
+ [TestMethod]
+ public void TestBoolean_False()
+ {
+ TestJsonTransformation(@"{
+ 'value': false
+ }",
+ @"{
+ 'result': '$.value->ToDecimal()'
+ }",
+ @"{
+ 'result': 0.0
+ }");
+ }
+
+ [TestMethod]
+ public void TestNull()
+ {
+ TestJsonTransformation(@"{
+ 'value': null
+ }",
+ @"{
+ 'result': '$.value->ToDecimal()'
+ }",
+ @"{
+ 'result': null
+ }");
+ }
+ }
+}
diff --git a/src/JSLTSharp.Tests/EmbededFunctions/ValueTransformations/ToLowerTransformTests.cs b/src/JSLTSharp.Tests/EmbededFunctions/ValueTransformations/ToLowerTransformTests.cs
new file mode 100644
index 0000000..ad317f3
--- /dev/null
+++ b/src/JSLTSharp.Tests/EmbededFunctions/ValueTransformations/ToLowerTransformTests.cs
@@ -0,0 +1,64 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace JSLTSharp.Tests.Transforms
+{
+ [TestClass]
+ public class ToLowerTransformTests : BaseTestsClass
+ {
+ [TestMethod]
+ public void TestValidResult()
+ {
+ TestJsonTransformation(@"{
+ 'upper': 'AZERTY'
+ }",
+ @"{
+ 'lower': '$.upper->ToLower()'
+ }",
+ @"{
+ 'lower': 'azerty'
+ }");
+ }
+
+ [TestMethod]
+ public void TestNumber()
+ {
+ TestJsonTransformation(@"{
+ 'upper': 123
+ }",
+ @"{
+ 'lower': '$.upper->ToLower()'
+ }",
+ @"{
+ 'lower': 123
+ }");
+ }
+
+ [TestMethod]
+ public void TestNull()
+ {
+ TestJsonTransformation(@"{
+ 'upper': null
+ }",
+ @"{
+ 'lower': '$.upper->ToLower()'
+ }",
+ @"{
+ 'lower': null
+ }");
+ }
+
+ [TestMethod]
+ public void TestMixedCase()
+ {
+ TestJsonTransformation(@"{
+ 'value': 'Hello World'
+ }",
+ @"{
+ 'result': '$.value->ToLower()'
+ }",
+ @"{
+ 'result': 'hello world'
+ }");
+ }
+ }
+}
diff --git a/src/JSLTSharp.Tests/EmbededFunctions/ValueTransformations/TrimTransformTests.cs b/src/JSLTSharp.Tests/EmbededFunctions/ValueTransformations/TrimTransformTests.cs
new file mode 100644
index 0000000..32ac63f
--- /dev/null
+++ b/src/JSLTSharp.Tests/EmbededFunctions/ValueTransformations/TrimTransformTests.cs
@@ -0,0 +1,92 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace JSLTSharp.Tests.Transforms
+{
+ [TestClass]
+ public class TrimTransformTests : BaseTestsClass
+ {
+ [TestMethod]
+ public void TestLeadingAndTrailingWhitespace()
+ {
+ TestJsonTransformation(@"{
+ 'value': ' hello '
+ }",
+ @"{
+ 'result': '$.value->Trim()'
+ }",
+ @"{
+ 'result': 'hello'
+ }");
+ }
+
+ [TestMethod]
+ public void TestLeadingWhitespaceOnly()
+ {
+ TestJsonTransformation(@"{
+ 'value': ' hello'
+ }",
+ @"{
+ 'result': '$.value->Trim()'
+ }",
+ @"{
+ 'result': 'hello'
+ }");
+ }
+
+ [TestMethod]
+ public void TestTrailingWhitespaceOnly()
+ {
+ TestJsonTransformation(@"{
+ 'value': 'hello '
+ }",
+ @"{
+ 'result': '$.value->Trim()'
+ }",
+ @"{
+ 'result': 'hello'
+ }");
+ }
+
+ [TestMethod]
+ public void TestNoWhitespace()
+ {
+ TestJsonTransformation(@"{
+ 'value': 'hello'
+ }",
+ @"{
+ 'result': '$.value->Trim()'
+ }",
+ @"{
+ 'result': 'hello'
+ }");
+ }
+
+ [TestMethod]
+ public void TestNumber()
+ {
+ TestJsonTransformation(@"{
+ 'value': 123
+ }",
+ @"{
+ 'result': '$.value->Trim()'
+ }",
+ @"{
+ 'result': 123
+ }");
+ }
+
+ [TestMethod]
+ public void TestNull()
+ {
+ TestJsonTransformation(@"{
+ 'value': null
+ }",
+ @"{
+ 'result': '$.value->Trim()'
+ }",
+ @"{
+ 'result': null
+ }");
+ }
+ }
+}
diff --git a/src/JSLTSharp/JsonTransforms/EmbededFunctions/ValueTransformations/ToDecimalTransformOperation.cs b/src/JSLTSharp/JsonTransforms/EmbededFunctions/ValueTransformations/ToDecimalTransformOperation.cs
new file mode 100644
index 0000000..0f587fd
--- /dev/null
+++ b/src/JSLTSharp/JsonTransforms/EmbededFunctions/ValueTransformations/ToDecimalTransformOperation.cs
@@ -0,0 +1,37 @@
+using JSLTSharp.JsonTransforms.Abstractions;
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+
+namespace JSLTSharp.JsonTransforms.EmbededFunctions.ValueTransformations
+{
+ public class ToDecimalTransformOperation : IJsonTransformCustomOperation
+ {
+ ///
+ public string OperationName => "ToDecimal";
+
+ ///
+ public JToken Apply(JToken dataSource, JToken objectToApplyTo, IList parameters)
+ {
+ switch (objectToApplyTo.Type)
+ {
+ case JTokenType.String:
+ var stringValue = objectToApplyTo.Value();
+ if (decimal.TryParse(stringValue, NumberStyles.Any, CultureInfo.InvariantCulture, out decimal convertedString))
+ return JValue.FromObject(convertedString);
+ else
+ return JValue.CreateNull();
+ case JTokenType.Integer:
+ return JValue.FromObject((decimal)objectToApplyTo.Value());
+ case JTokenType.Float:
+ return JValue.FromObject((decimal)objectToApplyTo.Value());
+ case JTokenType.Boolean:
+ var boolValue = objectToApplyTo.Value();
+ return JValue.FromObject(boolValue ? 1m : 0m);
+ default:
+ return JValue.CreateNull();
+ }
+ }
+ }
+}
diff --git a/src/JSLTSharp/JsonTransforms/EmbededFunctions/ValueTransformations/ToLowerTransformationOperation.cs b/src/JSLTSharp/JsonTransforms/EmbededFunctions/ValueTransformations/ToLowerTransformationOperation.cs
new file mode 100644
index 0000000..e5fbab0
--- /dev/null
+++ b/src/JSLTSharp/JsonTransforms/EmbededFunctions/ValueTransformations/ToLowerTransformationOperation.cs
@@ -0,0 +1,21 @@
+using JSLTSharp.JsonTransforms.Abstractions;
+using Newtonsoft.Json.Linq;
+using System.Collections.Generic;
+
+namespace JSLTSharp.JsonTransforms.EmbededFunctions.ValueTransformations
+{
+ public class ToLowerTransformationOperation : IJsonTransformCustomOperation
+ {
+ ///
+ public virtual string OperationName => "ToLower";
+
+ ///
+ public virtual JToken Apply(JToken dataSource, JToken objectToApplyTo, IList parameters)
+ {
+ if (objectToApplyTo.Type != JTokenType.String)
+ return objectToApplyTo;
+
+ return objectToApplyTo.ToString().ToLowerInvariant();
+ }
+ }
+}
diff --git a/src/JSLTSharp/JsonTransforms/EmbededFunctions/ValueTransformations/TrimTransformOperation.cs b/src/JSLTSharp/JsonTransforms/EmbededFunctions/ValueTransformations/TrimTransformOperation.cs
new file mode 100644
index 0000000..498c943
--- /dev/null
+++ b/src/JSLTSharp/JsonTransforms/EmbededFunctions/ValueTransformations/TrimTransformOperation.cs
@@ -0,0 +1,21 @@
+using JSLTSharp.JsonTransforms.Abstractions;
+using Newtonsoft.Json.Linq;
+using System.Collections.Generic;
+
+namespace JSLTSharp.JsonTransforms.EmbededFunctions.ValueTransformations
+{
+ public class TrimTransformOperation : IJsonTransformCustomOperation
+ {
+ ///
+ public virtual string OperationName => "Trim";
+
+ ///
+ public virtual JToken Apply(JToken dataSource, JToken objectToApplyTo, IList parameters)
+ {
+ if (objectToApplyTo.Type != JTokenType.String)
+ return objectToApplyTo;
+
+ return objectToApplyTo.ToString().Trim();
+ }
+ }
+}
diff --git a/src/JSLTSharp/JsonTransforms/Extensions/JsonTransformExtensions.cs b/src/JSLTSharp/JsonTransforms/Extensions/JsonTransformExtensions.cs
index 84e7463..c0d87f8 100644
--- a/src/JSLTSharp/JsonTransforms/Extensions/JsonTransformExtensions.cs
+++ b/src/JSLTSharp/JsonTransforms/Extensions/JsonTransformExtensions.cs
@@ -16,9 +16,12 @@ public static void RegisterJsonCustomTransformFunctions(this IServiceCollection
serviceCollection.AddSingleton();
serviceCollection.AddSingleton();
serviceCollection.AddSingleton();
+ serviceCollection.AddSingleton();
serviceCollection.AddSingleton();
serviceCollection.AddSingleton();
serviceCollection.AddSingleton();
+ serviceCollection.AddSingleton();
+ serviceCollection.AddSingleton();
serviceCollection.AddSingleton();
serviceCollection.AddSingleton();
@@ -27,5 +30,17 @@ public static void RegisterJsonCustomTransformFunctions(this IServiceCollection
serviceCollection.AddSingleton();
serviceCollection.AddSingleton();
}
+
+ ///
+ /// Register the JsonTransform engine along with all built-in transformation functions in the service collection.
+ /// This is a convenience method that combines with
+ /// registering the engine itself.
+ ///
+ /// The service collection to register dependencies into.
+ public static void AddJsonTransform(this IServiceCollection serviceCollection)
+ {
+ serviceCollection.RegisterJsonCustomTransformFunctions();
+ serviceCollection.AddSingleton();
+ }
}
}