Skip to content

External methods

External methods are methods you write in C# and register so transformers can call them. The easiest way is the JoltExternalMethod attribute from the Jolt.Library namespace.

using Jolt.Library;
namespace JoltExample;
public class TransformerMethods
{
[JoltExternalMethod]
public static bool IsNotNull(string value) => value != null;
}

To give the method a different name inside transformers, pass an alias: [JoltExternalMethod("differentName")].

Register the class when you create the transformer:

using Jolt.Json.Newtonsoft;
public string TransformationExample(string transformerJson, string sourceJsonDocument)
{
var transformer = JoltJsonTransformer.DefaultWith<TransformerMethods>(transformerJson);
return transformer.Transform(sourceJsonDocument);
}

Then call it like any library method:

transformer.json
{
"result": "#IsNotNull(#valueOf($.stringValue))"
}
source.json
{
"stringValue": "not null"
}
output.json
{
"result": true
}

A method whose result is written directly to the output, as above, must return one of:

  • a JSON-compatible value (string, boolean, number, …)
  • an IJsonToken
  • an EvaluationResult
  • any other object, which is serialized to JSON

Custom types are serialized with camelCase property names, so output style stays consistent without per-context configuration.

External methods can also be instance methods.

[JoltExternalMethod]
public string ReverseString(string value) => new string(value.Reverse().ToArray());

Pass an instance when you create the transformer. It’s used for every instance-method call during transformation.

var transformer = JoltJsonTransformer.DefaultWith<TransformerMethods>(transformerJson, new TransformerMethods());

External methods support piping like any other method:

{
"reversed": "#valueOf($.stringValue)->#ReverseString()"
}

With the same source document as before, the output is:

{
"reversed": "llun ton"
}

External methods can accept a Jolt lambda. Declare the parameter as a Func<> whose type arguments are any types Jolt external methods support. Lambdas with one or two parameters and a return value are currently supported.

[JoltExternalMethod("convertAllStringsToLongs")]
public static IEnumerable<long> ConvertAllStringsToLongs(IEnumerable<string> sequence, Func<string, long> convertStringToLong)
{
foreach (var value in sequence)
{
yield return convertStringToLong(value);
}
}
{
"converted": "#valueOf($.some.stringArray)->#convertAllStringsToLongs(@x: #toInteger(@x))"
}
public sealed class ComplexObject
{
public int Id { get; set; }
public long Value { get; set; }
}
[JoltExternalMethod("accumulateWithCustomType")]
public static IEnumerable<ComplexObject> AccumulateWithCustomType(IEnumerable<long> sequence, Func<ComplexObject, long, long> accumulate)
{
var complexObject = new ComplexObject { Id = 0, Value = 0 };
foreach (var value in sequence)
{
complexObject.Id++;
complexObject.Value = accumulate(complexObject, value);
yield return complexObject;
}
}
{
"accumulated": "#valueOf($.some.integerArray)->#accumulateWithCustomType(@x;@y: @x.value + @y)"
}

With integerArray set to [1, 2, 3, 4], the result is:

{
"accumulated": [
{ "id": 1, "value": 1 },
{ "id": 2, "value": 3 },
{ "id": 3, "value": 6 },
{ "id": 4, "value": 10 }
]
}

Notice that inside the lambda, @x.value uses the camelCase name of the C# Value property.

See manual registration to register methods explicitly with MethodRegistration.