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

独立模式Durable Azure Function传递DateOnly触发JsonException问题

Durable Azure Function独立模式下DateOnly参数传递问题

开发独立模式的Durable Azure Function时,通过TaskOrchestrationContext.CallActivityAsync传递DateOnly作为带[ActivityTrigger]的活动函数输入参数会抛出JsonException,但将DateOnly包装在类中传递则可正常运行。

错误信息

Exception: Microsoft.Azure.Functions.Worker.FunctionInputConverterException: Error converting 1 input parameters for Function 'WriteDateOnly': Cannot convert input parameter 'today' to type 'System.DateOnly' from type 'System.String'. Error:System.Text.Json.JsonException: '-' is an invalid end of a number. Expected a delimiter. Path: $ | LineNumber: 0 | BytePositionInLine: 4.

问题

在Durable Azure Function中,是否必须将DateOnly参数包装在类中?

可复现代码示例

主函数类

using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.DurableTask;
using Microsoft.DurableTask.Client;

namespace Sandbox.Functions
{
    public class DateOnlyOrchestrator
    {
        [Function("DateOnlyOrchestratorApi")]
        public async Task<HttpResponseData> RunApi(
            [HttpTrigger] HttpRequestData request,
            [DurableClient] DurableTaskClient durableTaskClient)
        {
            var today = new DateOnly(2023, 4, 11);

            var orchestrationInstanceId = await durableTaskClient
                .ScheduleNewOrchestrationInstanceAsync("DateOnlyOrchestrator", today)
                .ConfigureAwait(false);

            return durableTaskClient.CreateCheckStatusResponse(request, orchestrationInstanceId);
        }

        [Function("DateOnlyOrchestrator")]
        public async Task Run(
            [OrchestrationTrigger] TaskOrchestrationContext taskOrchestrationContext,
            DateOnly today)
        {
            var wrappedDateOnly = new WrappedDateOnly
            {
                Today = today,
            };

            // 此活动调用成功
            await taskOrchestrationContext
                .CallActivityAsync("WriteWrappedDateOnly", wrappedDateOnly)
                .ConfigureAwait(true);

            // 调用此活动时抛出JsonException
            await taskOrchestrationContext
                .CallActivityAsync("WriteDateOnly", today)
                .ConfigureAwait(true);

        }

        [Function("WriteWrappedDateOnly")]
        public Task WriteWrappedDateOnly(
            [ActivityTrigger] WrappedDateOnly today)
        {
            Console.WriteLine($"Today is: {today.Today}");
            return Task.CompletedTask;
        }

        [Function("WriteDateOnly")]
        public Task WriteDateOnly(
            [ActivityTrigger] DateOnly today)
        {
            Console.WriteLine($"Today is: {today}");
            return Task.CompletedTask;
        }
    }

    public class WrappedDateOnly
    {
        public DateOnly Today { get; set; }
    }
}

Program.cs

using Microsoft.Extensions.Hosting;

var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults()
    .Build();

host.Run();

解答

原因

这是Durable Task框架默认的System.Text.Json序列化/反序列化逻辑导致的问题:

  • 当传递单独的DateOnly值时,它会被序列化为纯字符串(比如"2023-04-11");
  • 活动函数的输入转换器尝试直接将该字符串反序列化为DateOnly类型时,会错误地将字符串开头的数字部分当作数值解析,遇到-符号时触发格式错误;
  • 当DateOnly被包装在类中时,JSON结构是标准对象({"Today":"2023-04-11"}),转换器能正确识别字符串对应的属性类型,完成反序列化。

解决方案:并非必须包装类

你可以通过以下两种方式替代包装类的方案:

1. 配置自定义Json转换器

在Program.cs中为Functions Worker添加DateOnly的自定义Json转换器,让框架能正确处理单独的DateOnly值:

using Microsoft.Extensions.Hosting;
using System.Text.Json;
using System.Text.Json.Serialization;

var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults(builder =>
    {
        builder.Services.Configure<Microsoft.Azure.Functions.Worker.Json.JsonSerializerOptions>(options =>
        {
            options.Converters.Add(new JsonStringEnumConverter());
            options.Converters.Add(new DateOnlyJsonConverter());
        });
    })
    .Build();

host.Run();

// 自定义DateOnly转换器
public class DateOnlyJsonConverter : JsonConverter<DateOnly>
{
    public override DateOnly Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        return DateOnly.Parse(reader.GetString()!);
    }

    public override void Write(Utf8JsonWriter writer, DateOnly value, JsonSerializerOptions options)
    {
        writer.WriteStringValue(value.ToString("O"));
    }
}

2. 手动传递字符串并解析

在编排器中传递DateOnly的字符串表示,在活动函数内手动解析:

  • 编排器端修改调用代码:
// 传递格式化后的字符串
await taskOrchestrationContext.CallActivityAsync("WriteDateOnly", today.ToString("O"));
  • 活动函数修改参数类型并解析:
[Function("WriteDateOnly")]
public Task WriteDateOnly([ActivityTrigger] string todayStr)
{
    DateOnly today = DateOnly.Parse(todayStr);
    Console.WriteLine($"Today is: {today}");
    return Task.CompletedTask;
}

总结

将DateOnly包装在类中是可行方案,但并非必须。通过配置自定义Json转换器或手动处理字符串解析,同样可以解决单独传递DateOnly参数时的序列化问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 05:47:40