Optimizing JSON data processing in Logic App with map and reduce

Peter KARDA
Published by Peter
Category : Azure / Logic Apps
06/10/2020

Not while ago a colleague of mine asked me to take a look at his Logic App. It has a HTTP trigger with JSON data on the input. The Logic App processed the data (JSON array) with a For-Each action and inside of the action there was an another For-Each action to proceed the children’s arrays. With certain simplifications the Logic App looked more or less like this:

Nested For Each

 

It’s straightforward to do it like this however the performance of such nested For-Each actions is not always the best. I’ve realized that a while ago the Inline Code action was added to Logic Apps. It allows executing a few lines of JavaScript code. JavaScript is quite powerful when it comes to manipulating with JSON data.

 

MEET INLINE CODE

The Inline Code is a Logic App action that allows you to add and execute a few lines of code (for now we can use only JavaScript) as a step in Logic App workflow.

Above that the Inline Code action:

  • Has access to workflowContext (trigger.body). Variable actions are not yet supported ;
  • Uses Node.js behind ;
  • Supports IntelliSence and syntax highlighting.

 

A bit special requirement is that the Logic App with that action has to be associated to an Integration Account (but nothing else has to be added to the Integration Account).

 

PUTTING IT IN ACTION

Let’s go back to our initial problem. In our example we’ll have inputData with array of orders. Each order has the order lines and each order line has a price. Our goal will be to return a JSON array with order’s id and total price of its order lines prices by using the Inline Code action with JavaScript.

Here are the input data:

{
    "inputData": {
        "orders": [
            {
                "id": 100,
                "orderLines": [
                    {
                        "name": "order item 11",
                        "price": 128
                    },
                    {
                        "name": "order item 12",
                        "price": 56
                    }
                ]
            },
            {
                "id": 101,
                "orderLines": [
                    {
                        "name": "order item 21",
                        "price": 200
                    },
                    {
                        "name": "order item 22",
                        "price": 20
                    }
                ]
            }
        ]
    }
}

and here is our expected result:

[
    {
        "orderId": 100,
        "totalPrice": 184
    },
    {
        "orderId": 101,
        "totalPrice": 220
    }
]

 

I’ve already mentioned that Inline Code action has access to workflowContext so we can easily extract the data from the Logic App trigger.

var orders = workflowContext.trigger.outputs.body.inputData.orders;

Now, we can loop through the orders and its order lines by using for or foreach loop and generate the result. However, JavaScript provides more powerful methods to do it easier and those are map() and reduce(). Let’s quickly look at what are those methods doing.

The map() method creates a new array with the results of calling a provided function on every element in the calling array.

var array1 = [1, 4, 9, 16];
// pass a function to map
const map1 = array1.map(x => x * 2);
console.log(map1);
// expected output: Array [2, 8, 18, 32]

The reduce() method executes a reducer function (that you provide) on each element of the array, resulting in a single output value.

const array1 = [1, 2, 3, 4];
const reducer = (accumulator, currentValue) => accumulator + currentValue;
// 1 + 2 + 3 + 4
console.log(array1.reduce(reducer));
// expected output: 10
// 5 + 1 + 2 + 3 + 4
console.log(array1.reduce(reducer, 5));
// expected output: 15

So let’s use those methods to extract our data from orders obtained from workflowContext and transform it to the expected result.

var orders = workflowContext.trigger.outputs.body.inputData.orders;
// create new ordersWithPrice array from orders and apply the function on each element
var ordersWithPrice = orders.map(order => {
    // calculate total price of order lines
    const totalPrice = order.orderLines.reduce((accumulator, orderLine) => accumulator + orderLine.price, 0);
// retun new array element (object)
return { orderId:o.id, totalPrice:totalPrice};
});

Now we’re done and it’s enough just to put the code above to the Inline Code and return the result. Isn’t that great?

 

THE FINAL LOGIC APP

In the final Logic App (see image below), I’ve written the transformation as a one-liner. That shows how powerful JavaScript could be when we need to transform the JSON data (and there are other helpful methods for working with arrays not mentioned in the article). This approach might not be preferred by everyone. Yes, it’s more clear to see the execution of each iteration in a For-Each action. But if the performance is the priority, then there is no question about the use of the Inline Code. This Logic App executes in a fraction of time compared to the original version with the nested For-Each actions.

 

Inlien Code - the final solution