Microsoft offers a few different solutions to perform message transformations in Logic Apps. One of them I described before in ‘Translating JSON messages with Logic Apps’. Liquid is considered as the new way forward to translate JSON and XML messages. XSLT still has strong support if you’re working with XML documents but if you’re working with the JSON message format Liquid is your friend.

Liquid is an open source template language created by Shopify. Microsoft uses the .NET implementation DotLiquid under the hood of their Liquid connectors. The usage of Liquid transforms in Logic Apps require an integration account. Integration accounts are not available as a serverless / consumption based service, and have a fixed price tag that forms a serious barrier for those that only have a need for a handful of message transformations.

Although integration accounts offer more functionality than merely Liquid transforms (EDI, B2B) its main use seems to be for Liquid transformations among a few customers I’ve engaged with recently.

Given DotLiquid is open source I took the challenge to build a serverless Azure Function to perform Liquid transforms with on-par functionality compared to Logic Apps Liquid transformations (JSON and XML to JSON, XML or plain text). The main objective was to no longer rely on an integration account and saving $5000 (!) on an annual basis. Combine this with serverless Logic Apps and the API Management consumption tier and you can potentially run an iPaaS for pennies. Take that MuleSoft…

I’ve published my solution on Github accompanied by documentation on how to use it. Usage doesn’t restrict itself to Logic Apps. The solution is available as a V1 Azure Function, mainly due to the missing Swagger support in Azure Functions V2. Azure Functions with a Swagger definition make for excellent integration with Logic Apps, as documented by Microsoft here. The Logic Apps designer interprets the Swagger automatically making consumption of the function a drag and drop experience.

The actual Liquid transforms are stored in the storage account associated with the Azure function, further reducing the amount of code required thanks to function bindings:

[FunctionName("LiquidTransformer")]
public static async Task Run([HttpTrigger(AuthorizationLevel.Function, "post", Route = "liquidtransformer/{liquidtransformfilename}")] HttpRequestMessage req,
[Blob("liquid-transforms/{liquidtransformfilename}", FileAccess.Read)] Stream inputBlob,
TraceWriter log)
{
log.Info("C# HTTP trigger function processed a request.");
}

The Azure Function takes the Liquid transform input as the function’s request body. The filename of the Liquid transform as stored in the storage account is part of the URL path, making is possible to perform the function binding with the blob.

Once the Swagger is enabled we can simply use the Azure Function connector in a Logic App and provide the necessary details of the transformation we want to execute:

The function supports JSON and XML as input types, specified in the Content-Type HTTP header. The expected output type has to be specified in the Accept header.

Using the following HTTP payload

POST /api/liquidtransformer/customext.liquid HTTP/1.1
Host: localhost:7071
Content-Type: application/json
Accept: application/json

{
"name": "olaf"
}

With the following Liquid template:

{
"fullName": "{{content.name | upcase }}"
}

Results in the following JSON output:

{
"fullName": "OLAF"
}

The benefits don’t stop at simple cost savings. Thanks to the DotLiquid extensible framework you can create your own filters, tags, etc. If you’ve ever tried to perform basic character padding with standard Liquid templates you’ll realise the power of custom filters…

Source code of this solution is published under the MIT license, so feel free to use and redistribute. Enjoy!