You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Newtonsoft.Json递归解析Logic App工作流的Action关系

解析Logic App Standard工作流JSON,提取Action的依赖与父层级

问题描述

我正在处理Logic App Standard工作流的JSON定义文件,其中actions字段对应工作流的执行步骤。每个Action可能包含子Action,因此存在父Action层级关系;Action的执行顺序由指向其他Action的runAfter属性决定。

我的需求是用C#(基于Newtonsoft.Json)处理任意工作流JSON,列出每个Action对应的runAfter依赖项以及它的父Action。但我对Newtonsoft.Json不熟悉,不知道如何检测子Action并完成递归解析。

示例工作流JSON如下:

{"definition": {"$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#","actions": {"For_each_result_set": {"actions": {"For_each_(row)_active_widget": {"actions": {"Insert_row_to_acme_job_status": {"inputs": {"parameters": {"setColumns": {"ClientTrackingID": "@{variables('clientTrackingId')}","WidgetId": "@{items('For_each_(row)_active_widget')?['widgetID']}"},"tableName": "[acme].[acme_job_status]"},"serviceProviderConfiguration": {"connectionName": "sql-4","operationId": "insertRow","serviceProviderId": "/serviceProviders/sql"}},"type": "ServiceProvider"},"Send_message_to_get-widget-responses_(topic)": {"inputs": {"body": {"Properties": {"clientTrackingId": "@{variables('clientTrackingId')}","widgetId": "@{items('For_each_(row)_active_widget')?['widgetID']}"},},"host": {"connection": {"referenceName": "servicebus-2"}},"method": "post","path": "/@{encodeURIComponent(encodeURIComponent('get-widget-responses'))}/messages","queries": {"systemProperties": "None"}},"runAfter": {"Insert_row_to_acme_job_status": ["SUCCEEDED"]},"type": "ApiConnection"}},"foreach": "@items('For_each_result_set')","type": "Foreach"}},"foreach": "@body('Get_Active_Widgets')?['resultSets']","runAfter": {"Get_Active_Widgets": ["SUCCEEDED"]},"type": "Foreach"},"Get_Active_Widgets": {"description": "","inputs": {"parameters": {"includeEmptyResultSets": true,"storedProcedureName": "procname"},"serviceProviderConfiguration": {"connectionName": "sql-4","operationId": "executeStoredProcedure","serviceProviderId": "/serviceProviders/sql"}},"runAfter": {"Initialise_Client_Tracking_Id": ["SUCCEEDED"]},"type": "ServiceProvider"},"Initialise_Client_Tracking_Id": {"description": "","inputs": {"variables": [{"name": "clientTrackingId","type": "string","value": "@{workflow().run.name}"}]},"runAfter": {},"type": "InitializeVariable"}},"contentVersion": "1.0.0.0","outputs": {},"triggers": {"Recurrence": {"description": "","recurrence": {"frequency": "Day","interval": 1,"schedule": {"hours": ["18"]},"timeZone": "GMT Standard Time"},"type": "Recurrence"}}},"kind": "Stateful"}

解决方案

1. 定义数据模型

创建用于映射JSON结构和存储解析结果的类:

// 存储每个Action的解析结果
public class ActionInfo
{
    public string ActionName { get; set; }
    public string ParentActionName { get; set; }
    public Dictionary<string, List<string>> RunAfterDependencies { get; set; } = new();
}

// 映射Action的核心JSON结构
public class LogicAction
{
    [JsonProperty("actions")]
    public Dictionary<string, LogicAction> SubActions { get; set; }
    
    [JsonProperty("runAfter")]
    public Dictionary<string, List<string>> RunAfter { get; set; }
}

// 映射整个工作流的JSON结构
public class LogicWorkflow
{
    [JsonProperty("definition")]
    public LogicWorkflowDefinition Definition { get; set; }
}

public class LogicWorkflowDefinition
{
    [JsonProperty("actions")]
    public Dictionary<string, LogicAction> Actions { get; set; }
}

2. 递归解析方法

编写递归方法遍历所有Action,记录父层级和runAfter依赖:

public static class WorkflowParser
{
    public static List<ActionInfo> ParseWorkflowActions(string workflowJson)
    {
        var result = new List<ActionInfo>();
        var workflow = JsonConvert.DeserializeObject<LogicWorkflow>(workflowJson);
        
        if (workflow?.Definition?.Actions == null)
            return result;
        
        // 从根级Actions开始递归解析
        ParseActions(workflow.Definition.Actions, null, result);
        return result;
    }

    private static void ParseActions(Dictionary<string, LogicAction> actions, string parentName, List<ActionInfo> result)
    {
        foreach (var actionKvp in actions)
        {
            var actionName = actionKvp.Key;
            var action = actionKvp.Value;
            
            // 添加当前Action的信息
            result.Add(new ActionInfo
            {
                ActionName = actionName,
                ParentActionName = parentName,
                RunAfterDependencies = action.RunAfter ?? new Dictionary<string, List<string>>()
            });
            
            // 递归处理子Actions
            if (action.SubActions != null && action.SubActions.Any())
            {
                ParseActions(action.SubActions, actionName, result);
            }
        }
    }
}

3. 使用示例

调用解析方法并输出结果:

// 替换为实际的工作流JSON内容
string workflowJson = "你的工作流JSON字符串";

var actionInfos = WorkflowParser.ParseWorkflowActions(workflowJson);

// 输出每个Action的详细信息
foreach (var info in actionInfos)
{
    Console.WriteLine($"Action名称: {info.ActionName}");
    Console.WriteLine($"父Action: {info.ParentActionName ?? "无"}");
    Console.WriteLine("RunAfter依赖:");
    foreach (var dep in info.RunAfterDependencies)
    {
        Console.WriteLine($"  {dep.Key}: {string.Join(", ", dep.Value)}");
    }
    Console.WriteLine("---");
}

关键说明

  • 模型类仅保留了核心字段,若需要type、inputs等其他属性,可直接在LogicAction类中添加对应的JsonProperty属性。
  • 递归方法会自动识别子Action并传递父层级名称,确保每个Action的父关系被正确记录。
  • runAfter字段直接映射为字典结构,键是依赖的Action名称,值是触发条件集合(如SUCCEEDED)。

内容的提问来源于stack exchange,提问作者user195166

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 16:39:52