Optimiser les traitements de données JSON dans une Logic App avec map et reduce

Peter KARDA
Publié par Peter KARDA
Catégorie : Azure / Logic Apps
20/10/2020

Un de mes collègue m’a récemment demandé de jeter un coup d’œil à sa Logic App. Elle utilisait un déclencheur HTTP avec des données JSON en entrée. La Logic App traitait les données (un tableau JSON) avec une action Foreach. Dans cette action, il y avait une autre action Foreach pour traiter les tableaux fils. En simplifiant, la Logic App ressemblait plus ou moins à cela :

 

Nested For Each

 

C’est la façon classique de procéder. Cependant, les performances sont rarement au rendez-vous avec des actions Foreach imbriquées comme cela. J’ai réalisé qu’il y a quelque temps une action Inline Code avait été ajoutée aux Logic Apps. Elle permet d’exécuter quelques lignes de code JavaScript. Le langage JavaScript est particulièrement puissant pour manipuler les données JSON.

 

PRÉSENTATION INLINE CODE

 

Inline Code est une action Logic App qui permet d’ajouter et d’exécuter quelques lignes de code (uniquement JavaScript, pour le moment), sous la forme d’une étape dans le flux de travail Logic App.

De plus, l’action Inline Code :

  • Accède au workflowContext (trigger.body). Les actions variables ne sont pas encore prises en charge ;
  • Utilise Node.js en fond ;
  • Prend en charge IntelliSence et la coloration syntaxique.

Une petite spécificité : pour utiliser cette action, vous devez lier la Logic App à votre Compte d’intégration (c’est la seule chose à ajouter à votre compte).

 

MISE EN APPLICATION

 

Revenons à notre problème initial. Nous allons prendre comme exemple un inputData avec un tableau contenant des commandes. Chaque commande se décompose en lignes de commande, et chaque ligne de commande a un prix. Notre but va être de renvoyer un tableau JSON contenant les identifiants des commandes et le prix total de leurs lignes de commande, en utilisant l’action Inline Code et du JavaScript.

Les données en entrée sont les suivantes :

 

{
    "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
                    }
                ]
            }
        ]
    }
}

 

Et le résultat attendu :

 

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

 

Comme mentionné précédemment, l’action Inline Code a accès au workflowContext. Nous pouvons donc facilement extraire les données à partir du déclencheur de la Logic App.

 

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

 

Nous pouvons maintenant itérer sur les commandes et les lignes de commande, en utilisant des boucles for ou for each, et générer le résultat. En fait, JavaScript fournit des méthodes plus simples et plus puissantes pour obtenir le même effet : map() et reduce(). Prenons un instant pour voir ce qu’elles font.

La méthode map() crée un nouveau tableau dont chaque élément contiendra le résultat de l’application de la fonction (passée en argument) sur l’élément correspondant dans le tableau d’origine.

 

var array1 = [1, 4, 9, 16];
// passe une fonction à map
const map1 = array1.map(x => x * 2);
console.log(map1);
// résultat attendu : Array [2, 8, 18, 32]

 

La méthode reduce() exécute une fonction de réduction (à lui fournir) sur chaque élément du tableau, et produit une valeur unique comme résultat.

 

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

 

Nous allons utiliser ces méthodes pour extraire nos données des commandes obtenues à partir du workflowContext et les mettre en forme pour arriver au résultat attendu.

 

var orders = workflowContext.trigger.outputs.body.inputData.orders;
// crée un nouveau tableau ordersWithPrice à partir des commandes et applique la fonction sur chaque élément
var ordersWithPrice = orders.map(order => {
    // calculate total price of order lines
    const totalPrice = order.orderLines.reduce((accumulator, orderLine) => accumulator + orderLine.price, 0);
// renvoie un nouvel élément (objet) de tableau
return { orderId:o.id, totalPrice:totalPrice};
});

 

Nous avons terminé. Il suffit maintenant de mettre le code ci-dessus dans un Inline Code et de renvoyer le résultat. Génial, non ?

 

LA LOGIC APP FINALE

 

Dans la Logic App finale (cf. image ci-dessous), j’ai écrit la transformation pour en faire un uniligne (one-liner). Cela montre à quel point JavaScript peut être efficace pour transformer des données JSON (et il existe d’autres méthodes utiles pour travailler avec des tableaux, qui ne sont pas dans cet article). Cette approche n’est peut-être pas celle que tout le monde préfèrera. On voit certes plus clairement l’exécution de chaque itération dans une action Foreach. Mais si la priorité est aux performances, alors l’utilisation de code inclus est le choix évident. Cette Logic App prend beaucoup moins de temps à s’exécuter que la version d’origine avec des actions Foreach imbriquées.

 

Inlien Code - the final solution