【Azure Developer】Azure Logic App 示例: 解析 Request Body 的 JSON 的表示式? triggerBody()?

路邊兩盞燈 發表於 2022-01-26

問題描述

通過Azure Logic App(邏輯應用)實現無程式碼的處理JSON資料。但是如何獲取Request Body中的一個屬性值呢? 例如:如何來獲取以下JSON結構中的 ObjectName 值?

Request物件中所含的Body內容(黃色高亮部分):

{
    "headers": {
        "Connection": "close",
        "Accept": "*/*",
        "Accept-Encoding": "br,gzip,deflate",
        "Accept-Language": "en",
        "Host": "prod-24.chinaeast2.logic.azure.cn",
        "User-Agent": "Mozilla/5.0,(Windows NT 10.0; Win64; x64),AppleWebKit/537.36,(KHTML, like Gecko),Chrome/97.0.4692.99,Safari/537.36,Edg/97.0.1072.69",
        "x-ms-client-session-id": "22ea27e05a1b4637b2aa8f2b3a7a3039",
        "x-ms-command-name": "RunWithPayloadConsumptionBlade.runTrigger",
        "x-ms-effective-locale": "en.en-us",
        "x-ms-client-request-id": "b73db2d0-ec46-436d-bfef-a2d2b7e9a00d",
        "origin": "https://portal.azure.cn",
        "sec-fetch-site": "same-site",
        "sec-fetch-mode": "cors",
        "sec-fetch-dest": "empty",
        "Content-Length": "913",
        "Content-Type": "application/json"
    },
    "body": [
        {
            "id": "4be730e8-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
            "topic": "/subscriptions/xxxx-xxxx-xxxx-xxxx-xxxx/...",
            "subject": "sqlPassword",
            "eventType": "Microsoft.KeyVault.SecretNearExpiry",
            "data": {
                "Id": "......",
                "VaultName": "xxxx-kv",
                "ObjectType": "Secret",
                "ObjectName": "sqlPassword",
                "Version": "ee550dxxxx",
                "NBF": null,
                "EXP": 1643111997
            },
            "dataVersion": "1",
            "metadataVersion": "1",
            "eventTime": "2022-01-25T11:54:50.6358008Z"
        }
    ]
}

如果直接在Logic App使用triggerBody()?['ObjectName'] 則遇見如下錯誤:

InvalidTemplate. Unable to process template language expressions in action 'Send_message' inputs at line '0' and column '0': 'The template language expression 'base64(triggerBody()?['objectName'])' cannot be evaluated because property 'objectName' cannot be selected. Array elements can only be selected using an integer index. Please see https://aka.ms/logicexpressions for usage details.'.

【Azure Developer】Azure Logic App 示例: 解析 Request Body 的 JSON 的表示式? triggerBody()?

 

問題分析

從錯誤訊息(Array elements can only be selected using an integer index)分析,因為 triggerBody() 函式獲取的物件為一個Array(陣列),所以無法查詢到ObjectName屬性。那麼分析Request所傳遞的Body JSON結構後,發現:

【Azure Developer】Azure Logic App 示例: 解析 Request Body 的 JSON 的表示式? triggerBody()?

1) Body中的最外層為一個陣列,以中括號 [] 表示

2) Body中的第二層為一個物件,以大括號 {}表示

3) ObjectName屬性位於data屬性中,為第三層。

所以也無法使用 triggerBody()[0]?['objectName'] 加上陣列索引後,依舊無法查詢到ObjectName屬性,錯誤資訊如下:

InvalidTemplate. Unable to process template language expressions in action 'Send_message' inputs at line '0' and column '0': 'The template language function 'base64' expects its parameter to be a string, an object or an array. The provided value is of type 'Null'. Please see https://aka.ms/logicexpressions#base64 for usage details.'.

【Azure Developer】Azure Logic App 示例: 解析 Request Body 的 JSON 的表示式? triggerBody()?

 

問題解決

所以為了解決JSON中陣列結構的取數問題,可以使用 Logic App的 Select Action 元件來完成資料的提取,但是如果能確定 HTTP Request Body中的陣列只有一個元素,則可以在表示式中指定索引號或使用fist(), last()等函式獲取陣列中的物件。然後通過['屬性名'] 來一級一級的獲取資料,如本文中獲取ObjectName屬性值得正確表示式為: 

triggerBody()[0]?['data']['objectName']

//或者

first(triggerBody())?['data']['ObjectName']

 

注:表示式中的“?”號表示如果triggerBody()[0]物件如果返回null或者undefined時,就直接返回null或 undefined,JSON操作不在執行後續物件data,objectName的查詢

【Azure Developer】Azure Logic App 示例: 解析 Request Body 的 JSON 的表示式? triggerBody()?

 

 

測試動畫

1) 在Logic App中測試

2) 在Service Bus Topic中驗證訊息是否正確傳遞

【Azure Developer】Azure Logic App 示例: 解析 Request Body 的 JSON 的表示式? triggerBody()?

 

 

 

參考資料

有關在 Azure 邏輯應用的表示式中使用函式的參考指南 : https://docs.microsoft.com/zh-cn/azure/logic-apps/workflow-definition-language-functions-reference#triggerBody