Azure 持久函数:JsonSerializationException 通过将复杂对象从触发器传递到协调器

Azure Durable Function: JsonSerializationException by passing complex object from trigger to orchestrator

我有一个带有 EventHubTrigger 的 azure 函数:

    [FunctionName("TradesDataProcessStarterEh")]
    public static async Task TradesDataProcessStarterEh([EventHubTrigger("aeehrobotronapiintegrationdev", Connection = "EventHubConnectionString", ConsumerGroup = "$Default")]
        EventData eventData, PartitionContext partitionContext, [OrchestrationClient] DurableOrchestrationClient starter, ILogger log)
    {
        if (partitionContext.PartitionId != "1")
            return;

        var orchestrationId = await starter.StartNewAsync("O_ProcessTradesFromEventHub", eventData);

        await partitionContext.CheckpointAsync();
    }

协调器函数正在接收事件数据:

    [FunctionName("O_ProcessTradesFromEventHub")]
    public static async Task ProcessTradesFromEventHub([OrchestrationTrigger] DurableOrchestrationContext context,
        ILogger log)
    {
        if (!context.IsReplaying)
            Console.WriteLine("O_ProcessTradesFromEventHub is triggered");

        var eventData = context.GetInput<EventData>();

        //do stuff...
    }

但是通过执行 context.GetInput() 我得到一个异常:

Function 'O_ProcessTradesFromEventHub (Orchestrator)' failed with an error. Reason: Newtonsoft.Json.JsonSerializationException: Unable to find a constructor to use for type Microsoft.Azure.EventHubs.EventData. A class should either have a default constructor, one constructor with arguments or a constructor marked with the JsonConstructor attribute. Path 'Body', line 1, position 81.

我可以想到 3 种可能的解决方案,您可以尝试:

  • 1 - 使用构造函数(可能通过继承?)将 EventData 包装在您自己的 class 中。
  • 2 - 尝试转换为对象,怀疑这是否有效,但值得一试,因为这是一个简单的修复。
  • 3 - 构建您自己的 DTO(数据传输对象)以将 EventData 转换为 <your class>,然后将 <your class> 传递给编排。

我认为 (3) 是最简洁的解决方案,您可以完全控制传递的内容,不幸的是,它可能是性能最低且最乏味的。

祝你好运!

使用 LINQ JSON - 一年后,但希望它能为其他人节省一些时间。

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

public static async Task Run(
    [OrchestrationTrigger] DurableOrchestrationContext context, ILogger log) {

    var eventData = context.GetInput<JObject>();
    log.LogInformation ($"Executing tasks with eventData = {eventData}");

    string step = (string)eventData.SelectToken("Step");
    log.LogInformation ($"Step = {step}");

}