I am trying to write a logic app to parse a Json Object and Update salesforce record. I am pretty new to both Salesforce and Azure logic apps, so I am trying to figure this out. Below is my Json File
{
"ContactId": null,
"Email": "asong#uog.com",
"IsInternalUpdate": false,
"Preferences": [
{
"PrefCode": "EmailOptIn",
"CurrentValue": "Yes",
"Locale": "en-US"
},
{
"PrefCode": "MobilePhone",
"CurrentValue": "1234567890",
"Locale": "en-US"
},
{
"PrefCode": "SMSOptIn",
"CurrentValue": "Yes",
"Locale": "en-US"
},
{
"PrefCode": "ProductTrends",
"CurrentValue": "ProductTrends,OffersPromotions",
"Locale": "en-US"
},
]
}
Based on email value, I need to update a custom object in Salesforce. From the preference array, Prefcode value maps to a field in Salesforce and Current value maps to field value. i.e below snippet translates to set the value for EmailOptIn field in Salesforce to "Yes"
{
"PrefCode": "EmailOptIn",
"CurrentValue": "Yes",
"Locale": "en-US"
}
So far, I was able to pass hardcoded values and successfully update salesforce record from logic app.
I am trying to set individual variables for each field, so that I can pass it directly to salesforce. I have two issues that I am running into
What is the best way to capture the field value mapping?
I have couple of fields that allow multi select, how do I set the multiselect values. Below is an example
{
"PrefCode": "ProductTrends",
"CurrentValue": "ProductTrends,OffersPromotions",
"Locale": "en-US"
}
Below is my logic app structure
1
2
What is the best way to capture the field value mapping?
I could able to achieve your requirement by constructing JSON with required details and used parse JSON step again. Below is the flow of the logic app that worked for me.
I have couple of fields that allow multi select, how do I set the multiselect values. Below is an example
I have converted the ProductTrends into array and retrieved each item using its index as below.
array(split(body('Parse_JSON_2')?['ProductTrends'],','))[0]
array(split(body('Parse_JSON_2')?['ProductTrends'],','))[1]
Alternatively, if it is possible to make things work from the target end for multiple values, you can send in array or string directly to salesforce.
Below is the complete JSON of my logic app.
{
"definition": {
"$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
"actions": {
"Compose": {
"inputs": {
"ContactId": null,
"Email": "asong#uog.com",
"IsInternalUpdate": false,
"Preferences": [
{
"CurrentValue": "Yes",
"Locale": "en-US",
"PrefCode": "EmailOptIn"
},
{
"CurrentValue": "1234567890",
"Locale": "en-US",
"PrefCode": "MobilePhone"
},
{
"CurrentValue": "Yes",
"Locale": "en-US",
"PrefCode": "SMSOptIn"
},
{
"CurrentValue": "ProductTrends,OffersPromotions",
"Locale": "en-US",
"PrefCode": "ProductTrends"
}
]
},
"runAfter": {},
"type": "Compose"
},
"Compose_2": {
"inputs": "#array(split(body('Parse_JSON_2')?['ProductTrends'],','))[0]",
"runAfter": {
"Parse_JSON_2": [
"Succeeded"
]
},
"type": "Compose"
},
"For_each": {
"actions": {
"Append_to_string_variable": {
"inputs": {
"name": "Preferences",
"value": "\"#{items('For_each')?['PrefCode']}\":\"#{items('For_each')?['CurrentValue']}\",\n"
},
"runAfter": {},
"type": "AppendToStringVariable"
}
},
"foreach": "#body('Parse_JSON')?['Preferences']",
"runAfter": {
"Initialize_variable": [
"Succeeded"
]
},
"type": "Foreach"
},
"Initialize_variable": {
"inputs": {
"variables": [
{
"name": "Preferences",
"type": "string"
}
]
},
"runAfter": {
"Parse_JSON": [
"Succeeded"
]
},
"type": "InitializeVariable"
},
"Parse_JSON": {
"inputs": {
"content": "#outputs('Compose')",
"schema": {
"properties": {
"ContactId": {},
"Email": {
"type": "string"
},
"IsInternalUpdate": {
"type": "boolean"
},
"Preferences": {
"items": {
"properties": {
"CurrentValue": {
"type": "string"
},
"Locale": {
"type": "string"
},
"PrefCode": {
"type": "string"
}
},
"required": [
"PrefCode",
"CurrentValue",
"Locale"
],
"type": "object"
},
"type": "array"
}
},
"type": "object"
}
},
"runAfter": {
"Compose": [
"Succeeded"
]
},
"type": "ParseJson"
},
"Parse_JSON_2": {
"inputs": {
"content": "#concat('{',slice(variables('Preferences'),0,lastIndexOf(variables('Preferences'),',')),'}')",
"schema": {
"properties": {
"EmailOptIn": {
"type": "string"
},
"MobilePhone": {
"type": "string"
},
"ProductTrends": {
"type": "string"
},
"SMSOptIn": {
"type": "string"
}
},
"type": "object"
}
},
"runAfter": {
"For_each": [
"Succeeded"
]
},
"type": "ParseJson"
}
},
"contentVersion": "1.0.0.0",
"outputs": {},
"parameters": {},
"triggers": {
"manual": {
"inputs": {
"schema": {}
},
"kind": "Http",
"type": "Request"
}
}
},
"parameters": {}
}
After following the above process, I could able to get the preferences values individually.
Related
I am struggling of finding a feasible solution for my Azure Logic App.
A HTTP Request-action call will list the virtual networks of an Azure subscription.
The response look somehow like this:
{
"value": [
{
"name": "virtualNetworkName1",
"id": "/subscriptions/111-222-333/resourceGroups/resourceGroupName1/providers/Microsoft.Network/virtualNetworks/virtualNetworkName1",
"etag": "W/\"11111-1111-111\"",
"type": "Microsoft.Network/virtualNetworks",
"location": "eastus",
"properties": {
"provisioningState": "Succeeded",
"resourceGuid": "111-1111-11111",
"addressSpace": {
"addressPrefixes": [
"192.168.0.0/25"
]
}
}
},
{
"name": "virtualNetworkName2",
"id": "/subscriptions/111-222-333/resourceGroups/resourceGroupName2/providers/Microsoft.Network/virtualNetworks/virtualNetworkName2",
"etag": "W/\"22222-2222-222\"",
"type": "Microsoft.Network/virtualNetworks",
"location": "westeurope",
"properties": {
"provisioningState": "Succeeded",
"resourceGuid": "222-2222-22222",
"addressSpace": {
"addressPrefixes": [
"192.168.1.0/24"
]
}
}
}
]
}
The resonse has even more properties which aren't necessary.
Regarding to this, I would like to use the HTTP Response-action in a JSON format with only a few properties:
Name
Id
Location
Like this:
[
{
"name": "virtualNetworkName1",
"id": "/subscriptions/111-222-333/resourceGroups/resourceGroupName1/providers/Microsoft.Network/virtualNetworks/virtualNetworkName1",
"location": "eastus"
},
{
"name": "virtualNetworkName2",
"id": "/subscriptions/111-222-333/resourceGroups/resourceGroupName2/providers/Microsoft.Network/virtualNetworks/virtualNetworkName2",
"location": "westeurope"
}
]
Is it possible to realize it with only Logic App native actions?
I have reproduced in my environment and got expected results as below:
Firstly, I have initialized your output in a variable and then used parse Json and compose to get required output:
Parse Json Schema:
{
"properties": {
"value": {
"items": {
"properties": {
"id": {
"type": "string"
},
"location": {
"type": "string"
},
"name": {
"type": "string"
}
},
"type": "object"
},
"type": "array"
}
},
"type": "object"
}
Output:
First json Output:
Second one:
Code view of Logic app:
{
"definition": {
"$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
"actions": {
"Compose": {
"inputs": {
"value": [
{
"etag": "W/\"11111-1111-111\"",
"id": "/subscriptions/111-222-333/resourceGroups/resourceGroupName1/providers/Microsoft.Network/virtualNetworks/virtualNetworkName1",
"location": "eastus",
"name": "virtualNetworkName1",
"properties": {
"addressSpace": {
"addressPrefixes": [
"192.168.0.0/25"
]
},
"provisioningState": "Succeeded",
"resourceGuid": "111-1111-11111"
},
"type": "Microsoft.Network/virtualNetworks"
},
{
"etag": "W/\"22222-2222-222\"",
"id": "/subscriptions/111-222-333/resourceGroups/resourceGroupName2/providers/Microsoft.Network/virtualNetworks/virtualNetworkName2",
"location": "westeurope",
"name": "virtualNetworkName2",
"properties": {
"addressSpace": {
"addressPrefixes": [
"192.168.1.0/24"
]
},
"provisioningState": "Succeeded",
"resourceGuid": "222-2222-22222"
},
"type": "Microsoft.Network/virtualNetworks"
}
]
},
"runAfter": {},
"type": "Compose"
},
"For_each": {
"actions": {
"Compose_2": {
"inputs": {
"id": "#items('For_each')?['id']",
"location": "#items('For_each')?['location']",
"name": "#items('For_each')?['name']"
},
"runAfter": {},
"type": "Compose"
}
},
"foreach": "#body('Parse_JSON')?['value']",
"runAfter": {
"Parse_JSON": [
"Succeeded"
]
},
"type": "Foreach"
},
"Parse_JSON": {
"inputs": {
"content": "#outputs('Compose')",
"schema": {
"properties": {
"value": {
"items": {
"properties": {
"id": {
"type": "string"
},
"location": {
"type": "string"
},
"name": {
"type": "string"
}
},
"type": "object"
},
"type": "array"
}
},
"type": "object"
}
},
"runAfter": {
"Compose": [
"Succeeded"
]
},
"type": "ParseJson"
}
},
"contentVersion": "1.0.0.0",
"outputs": {},
"parameters": {},
"triggers": {
"manual": {
"inputs": {
"schema": {}
},
"kind": "Http",
"type": "Request"
}
}
},
"parameters": {}
}
Now you will get required fields as I have got.
We have configured common alert schema for alerts and we are using a ticketing software and whenever we receive alert it should create a ticket.
In the logic app I have to make Post API call for creation of ticket with following json object, some fields are hard coded values:
{
"subject": "",
"Id": "123456789", // Hard code value
"priority": "",
"email": "test#test.com", // Hard code value
"status": "Open" // Hard code value
}
Parse Json sample payload schema for Alert:
{
"data": {
"alertContext": {
},
},
"customProperties": null,
"essentials": {
"alertContextVersion": "123",
"alertId": "123",
"alertRule": "Test Alerts",
"description": "test",
"severity": "Sev4"
}
},
"schemaId": "test"
}
I have to map "subject and "priority" fields with alert json object "description" and "severity":
subject-->description
priority --> severity // sev0 =high ,sev1=medium, sev2 =low
How can I achieve this using logic app?
After Parse JSON You can directly map its objects in the compose connector with the required fields. Below is my logic app flow.
You can use the below Code view to reproduce the same in your Logic app
{
"definition": {
"$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
"actions": {
"Compose": {
"inputs": {
"customProperties": null,
"data": {
"alertContext": {}
},
"essentials": {
"alertContextVersion": "123",
"alertId": "123",
"alertRule": "Test Alerts",
"description": "test",
"severity": "Sev4"
},
"schemaId": "test"
},
"runAfter": {},
"type": "Compose"
},
"Compose_2": {
"inputs": {
"Id": "123456789",
"email": "test#test.com",
"priority": "#{body('Parse_JSON')?['essentials']?['severity']}",
"status": "Open",
"subject": "#{body('Parse_JSON')?['essentials']?['description']}"
},
"runAfter": {
"Parse_JSON": [
"Succeeded"
]
},
"type": "Compose"
},
"Parse_JSON": {
"inputs": {
"content": "#outputs('Compose')",
"schema": {
"properties": {
"customProperties": {},
"data": {
"properties": {
"alertContext": {
"properties": {},
"type": "object"
}
},
"type": "object"
},
"essentials": {
"properties": {
"alertContextVersion": {
"type": "string"
},
"alertId": {
"type": "string"
},
"alertRule": {
"type": "string"
},
"description": {
"type": "string"
},
"severity": {
"type": "string"
}
},
"type": "object"
},
"schemaId": {
"type": "string"
}
},
"type": "object"
}
},
"runAfter": {
"Compose": [
"Succeeded"
]
},
"type": "ParseJson"
}
},
"contentVersion": "1.0.0.0",
"outputs": {},
"parameters": {},
"triggers": {
"manual": {
"inputs": {},
"kind": "Http",
"type": "Request"
}
}
},
"parameters": {}
}
Im getting a http response from Azure LogAnalytics, the response is a Json like this
{
"tables": [
{
"name": "PrimaryResult",
"columns": [
{
"name": "TimeGenerated",
"type": "datetime"
},
{
"name": "DestinationIP",
"type": "string"
},
{
"name": "DestinationUserName",
"type": "string"
},
{
"name": "country_name",
"type": "string"
},
{
"name": "country_iso_code",
"type": "string"
},
{
"name": "AccountCustomEntity",
"type": "string"
}
],
"rows": [
[
"2021-05-17T14:07:01.878Z",
"158.000.000.33",
"luis",
"United States",
"US",
"luis"
]
]
}
]
}
I will never get the same colums or sometimes i will get more rows with data like this
{
"tables": [
{
"name": "PrimaryResult",
"columns": [
{
"name": "Account",
"type": "string"
},
{
"name": "Computer",
"type": "string"
},
{
"name": "IpAddress",
"type": "string"
},
{
"name": "AccountType",
"type": "string"
},
{
"name": "Activity",
"type": "string"
},
{
"name": "LogonTypeName",
"type": "string"
},
{
"name": "ProcessName",
"type": "string"
},
{
"name": "StartTimeUtc",
"type": "datetime"
},
{
"name": "EndTimeUtc",
"type": "datetime"
},
{
"name": "ConnectinCount",
"type": "long"
},
{
"name": "timestamp",
"type": "datetime"
},
{
"name": "AccountCustomEntity",
"type": "string"
},
{
"name": "HostCustomEntity",
"type": "string"
},
{
"name": "IPCustomEntity",
"type": "string"
}
],
"rows": [
[
"abc\\abc",
"EQ-DC02.abc.LOCAL",
"0.0.0.0",
"User",
"4624 - An account was successfully logged on.",
"10 - RemoteInteractive",
"C:\\Windows\\System32\\svchost.exe",
"2021-05-17T15:02:25.457Z",
"2021-05-17T15:02:25.457Z",
2,
"2021-05-17T15:02:25.457Z",
"abc\\abc",
"EQ-DC02.abc.LOCAL",
"0.0.0.0"
],
[
"abc\\eona",
"EQPD-SW01.abc.LOCAL",
"0.0.0.0",
"User",
"4624 - An account was successfully logged on.",
"10 - RemoteInteractive",
"C:\\Windows\\System32\\svchost.exe",
"2021-05-17T15:21:45.993Z",
"2021-05-17T15:21:45.993Z",
1,
"2021-05-17T15:21:45.993Z",
"abc\\abc",
"EQPD-SW01.abc.LOCAL",
"0.0.0.0"
]
]
}
]
}
Im using Power Automate to parse this kind of Json to a Object or to make a response
the question is, how can i parse this "Columns" and "Rows" to a object?
Similar discussion happened in community forum and the solution identified was:
parse JSON and transform it to XML and then search keys with XPATH in Flow
I have a pipeline in DF2 that has to look at a folder in blob and process each of the 145 files sequentially into a database table. After each file has been loaded into the table, a stored procedure should be trigger that will check each record and either insert it, or update an existing record into a master table.
Looking online I feel as though I have tried every combination of "Get MetaData", "For Each", "LookUp" and "Assign Variable" activates that have been suggested but for some reason my Copy Data STILL picks up all files at the same time and runs 145 times.
Recently found a blog online that I followed to use "Assign Variable" as it will be useful for multiple file locations but it does not work for me. I need to read the files as CSVs to tables and not binary objects so therefore I think this is my issue.
{
"name": "BulkLoadPipeline",
"properties": {
"activities": [
{
"name": "GetFileNames",
"type": "GetMetadata",
"policy": {
"timeout": "7.00:00:00",
"retry": 0,
"retryIntervalInSeconds": 30,
"secureOutput": false,
"secureInput": false
},
"typeProperties": {
"dataset": {
"referenceName": "DelimitedText1",
"type": "DatasetReference",
"parameters": {
"fileName": "#item()"
}
},
"fieldList": [
"childItems"
],
"storeSettings": {
"type": "AzureBlobStorageReadSetting"
},
"formatSettings": {
"type": "DelimitedTextReadSetting"
}
}
},
{
"name": "CopyDataRunDeltaCheck",
"type": "ForEach",
"dependsOn": [
{
"activity": "BuildList",
"dependencyConditions": [
"Succeeded"
]
}
],
"typeProperties": {
"items": {
"value": "#variables('fileList')",
"type": "Expression"
},
"isSequential": true,
"activities": [
{
"name": "WriteToTables",
"type": "Copy",
"policy": {
"timeout": "7.00:00:00",
"retry": 0,
"retryIntervalInSeconds": 30,
"secureOutput": false,
"secureInput": false
},
"typeProperties": {
"source": {
"type": "DelimitedTextSource",
"storeSettings": {
"type": "AzureBlobStorageReadSetting",
"wildcardFileName": "*.*"
},
"formatSettings": {
"type": "DelimitedTextReadSetting"
}
},
"sink": {
"type": "AzureSqlSink"
},
"enableStaging": false,
"translator": {
"type": "TabularTranslator",
"mappings": [
{
"source": {
"name": "myID",
"type": "String"
},
"sink": {
"name": "myID",
"type": "String"
}
},
{
"source": {
"name": "Col1",
"type": "String"
},
"sink": {
"name": "Col1",
"type": "String"
}
},
{
"source": {
"name": "Col2",
"type": "String"
},
"sink": {
"name": "Col2",
"type": "String"
}
},
{
"source": {
"name": "Col3",
"type": "String"
},
"sink": {
"name": "Col3",
"type": "String"
}
},
{
"source": {
"name": "Col4",
"type": "String"
},
"sink": {
"name": "Col4",
"type": "String"
}
},
{
"source": {
"name": "DW Date Created",
"type": "String"
},
"sink": {
"name": "DW_Date_Created",
"type": "String"
}
},
{
"source": {
"name": "DW Date Updated",
"type": "String"
},
"sink": {
"name": "DW_Date_Updated",
"type": "String"
}
}
]
}
},
"inputs": [
{
"referenceName": "DelimitedText1",
"type": "DatasetReference",
"parameters": {
"fileName": "#item()"
}
}
],
"outputs": [
{
"referenceName": "myTable",
"type": "DatasetReference"
}
]
},
{
"name": "CheckDeltas",
"type": "SqlServerStoredProcedure",
"dependsOn": [
{
"activity": "WriteToTables",
"dependencyConditions": [
"Succeeded"
]
}
],
"policy": {
"timeout": "7.00:00:00",
"retry": 0,
"retryIntervalInSeconds": 30,
"secureOutput": false,
"secureInput": false
},
"typeProperties": {
"storedProcedureName": "[TL].[uspMyCheck]"
},
"linkedServiceName": {
"referenceName": "myService",
"type": "LinkedServiceReference"
}
}
]
}
},
{
"name": "BuildList",
"type": "ForEach",
"dependsOn": [
{
"activity": "GetFileNames",
"dependencyConditions": [
"Succeeded"
]
}
],
"typeProperties": {
"items": {
"value": "#activity('GetFileNames').output.childItems",
"type": "Expression"
},
"isSequential": true,
"activities": [
{
"name": "Create list from variables",
"type": "AppendVariable",
"typeProperties": {
"variableName": "fileList",
"value": "#item().name"
}
}
]
}
}
],
"variables": {
"fileList": {
"type": "Array"
}
}
}
}
The Details screen of the pipleline output shows the pipeline loops for the number of items in the blob but each time, the Copy Data and Stored Procedure are run for each file in the list at once as opposed to one at a time.
I feel like I am close to the answer but missing one vital part. Any help or suggestions are GREATLY appreciated.
Your payload is not correct.
GetMetadata actvitiy should not use the same dataset with Copy Activity.
GetMetadata activity should reference a dataset with a folder, the folder contains all file you want to deal with. but your dataset has 'filename' parameter.
use the output of the getMetadata activity as the input of forEach activity.
I have JSON below which I receive from external entity. As you can see requestbody parameter is appearing as string even though it's JSON. So how do I unescape it so I can correctly parse it downstream?
{
"emailaddress": "174181#mycomp.com",
"requestbody": "{\"Id\":\"57518139-687c-4223-b08b-342f4ff426ca\",\"Properties\":{\"PrincipalId\":\"d701e7aa-5a0a-4c4a-81be-4c4b7a3967ce\",\"RoleDefinitionId\":\"/subscriptions/64ba3e4c-45e3-4d55-8132-6731cf25547f/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635\",\"Scope\":\"/subscriptions/64ba3e4c-45e3-4d55-8132-6731cf25547f\"}}"
}
Use a Parse JSON Action as shown below:
Content:
{
"emailaddress": "174181#mycomp.com",
"requestbody": "{\"Id\":\"57518139-687c-4223-b08b-342f4ff426ca\",\"Properties\":{\"PrincipalId\":\"d701e7aa-5a0a-4c4a-81be-4c4b7a3967ce\",\"RoleDefinitionId\":\"/subscriptions/64ba3e4c-45e3-4d55-8132-6731cf25547f/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635\",\"Scope\":\"/subscriptions/64ba3e4c-45e3-4d55-8132-6731cf25547f\"}}"
}
Schema
{
"$schema": "http://json-schema.org/draft-04/schema#",
"properties": {
"emailaddress": {
"type": "string"
},
"requestbody": {
"type": "string"
}
},
"required": [
"emailaddress",
"requestbody"
],
"type": "object"
}
Initialize Variable
-Name = Variable Name
-Type = Object
-Value = json(body('Parse_JSON')['requestbody'])
Now you can extract the properties of your Json string as shown below:
variables('jsonobj')?['Properties']
Full Code view of my sample:
{
"definition": {
"$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
"actions": {
"Initialize_variable": {
"inputs": {
"variables": [
{
"name": "jsonobj",
"type": "Object",
"value": "#json(body('Parse_JSON')['requestbody'])"
}
]
},
"runAfter": {
"Parse_JSON": [
"Succeeded"
]
},
"type": "InitializeVariable"
},
"Parse_JSON": {
"inputs": {
"content": {
"emailaddress": "174181#mycomp.com",
"requestbody": "{\"Id\":\"57518139-687c-4223-b08b-342f4ff426ca\",\"Properties\":{\"PrincipalId\":\"d701e7aa-5a0a-4c4a-81be-4c4b7a3967ce\",\"RoleDefinitionId\":\"/subscriptions/64ba3e4c-45e3-4d55-8132-6731cf25547f/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635\",\"Scope\":\"/subscriptions/64ba3e4c-45e3-4d55-8132-6731cf25547f\"}}"
},
"schema": {
"$schema": "http://json-schema.org/draft-04/schema#",
"properties": {
"emailaddress": {
"type": "string"
},
"requestbody": {
"type": "string"
}
},
"required": [
"emailaddress",
"requestbody"
],
"type": "object"
}
},
"runAfter": {},
"type": "ParseJson"
},
"Response": {
"inputs": {
"body": "#variables('jsonobj')?['Properties']",
"statusCode": 200
},
"kind": "Http",
"runAfter": {
"Initialize_variable": [
"Succeeded"
]
},
"type": "Response"
}
},
"contentVersion": "1.0.0.0",
"outputs": {},
"parameters": {},
"triggers": {
"manual": {
"inputs": {
"schema": {}
},
"kind": "Http",
"type": "Request"
}
}
}
}
The easiest way is to use this expression:
#json(outputs('Mock_example_data').requestbody)
Below is an example using a Compose action to mock up your data and another Compose action as a simple proof of concept.