Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I merge the outputs from a For_Each loop in an Azure Logic App to a single flat array?

I have a For_Each loop in an Azure Logic App that calls another, nested, Logic App. The result from each iteration of the nested Logic Apps is a JSON object that contains an array of strings, like this:

{
 "Results": ["string a", "string b"]
}

So the output from my For_Each loop in the parent Logic App looks like this:

[
 {"Results": ["string a", "string b"]},
 {"Results": ["string c", "string d"]}
]

I want to put all these strings into a single flat list that I can pass to another action.

How can I do this? Is it possible using the workflow definition language and built-in functions, or do I need to use an external function (in a service, or an Azure Function)?

like image 454
Jude Fisher Avatar asked May 05 '17 18:05

Jude Fisher


2 Answers

There's a simpler solution, working with Array Variables. At the top level, outside the For Each loop, declare a variable with an InitializeVariable action:

"Initialize_Items_variable": {
    "inputs": {
        "variables": [
            {
                "name": "Items",
                "type": "Array",
                "value": []
            }
        ]
    },
    "runAfter": {},
    "type": "InitializeVariable"
}

Inside the For Each, use a AppendToArrayVariable action. You can append the Response object of the Nested Logic App you just called.

"Append_to_Items_variable": {
    "inputs": {
        "name": "Items",
        "value": "@body('Nested_Logic_App_Response')"
    },
    "runAfter": {
    },
    "type": "AppendToArrayVariable"
}

Hope it helps.

like image 117
Grazi Bonizi Avatar answered Sep 22 '22 23:09

Grazi Bonizi


Picking up on @DerekLi's useful comment above, it seems this is not possible at the time of writing with Logic Apps schema version 2016-06-01.

One of the great strengths of Logic Apps is the ability to leverage the power of Azure Functions to solve problems like this that can't (yet) be solved in the schema language.

Re-writing the array is trivial in c# within a function:

using System.Net;

public class Result
{
    public List<string> Results {get; set;}
}

public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)
{
    log.Info("C# HTTP trigger function processed a request.");

    var inputs = await req.Content.ReadAsAsync<List<Result>>();
    var outputs = new List<string>();

    foreach(var item in inputs)
    {
        log.Info(item.Results.ToString());
        outputs.AddRange(item.Results.Where(x => !string.IsNullOrEmpty(x)));
    }

    return req.CreateResponse(HttpStatusCode.OK, outputs);
}

And this function can then be passed the result of the For_Each loop:

"MyFunction": {
    "inputs": {
                "body": "@body('Parse_JSON')",
                "function": {
                    "id": "/subscriptions/{subscription-id}/resourceGroups/{resource-group-name}/providers/Microsoft.Web/sites/{function-app-name}/functions/{function-name}"
                },
                "method": "POST"
            },
            "runAfter": {
                "For_each": [
                    "Succeeded"
                ]
            },
            "type": "Function"
}
like image 35
Jude Fisher Avatar answered Sep 18 '22 23:09

Jude Fisher