使用 Azure Functions 3.0 中的属性将 Enum 序列化为字符串

2023-11-22

我尝试在 Azure Functions 3.0/3.1 应用程序中获取 HTTP 触发器来返回枚举的字符串表示形式,但没有任何运气。我已经尝试过 Core 3.0 和 Core 3.1。

给定这个类:

public enum TestEnum
{
   TestValue
}

public class TestClass
{ 
   public TestEnum Test { get; set; }
}

我期望这个 HTTP 触发:

[FunctionName("MyHttpTrigger")]
public static IActionResult Run(
   [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, ILogger log)
{
    return new OkObjectResult(new TestClass { Test = TestEnum.TestValue });
}

回来{ "test": "TestValue" }。相反,它返回{ "test": 0 }.

在 .Net Core 2 中,我可以使用以下方式装饰枚举[JsonConverter(typeof(StringEnumConverter))]从命名空间Newtonsoft.Json为了实现这一目标。现在这不起作用。

我知道 .Net Core 3 切换到了转换器System.Text.Json-namespace,所以我尝试用以下内容装饰相同的枚举[JsonConverter(typeof(JsonStringEnumConverter))]从命名空间System.Text.Json.Serialization。这也不起作用。

所有其他类似的问题要么说上述应该有效,要么,就像this,说通过配置 JsonOptions 来解决它.AddControllers() or .AddMvc()-chain,但是对于一个无法工作的函数应用程序。函数运行时负责设置控制器,因此我们无法直接访问进一步的配置。

使用核心工具的准系统 Azure Functions 项目应该可以重现该问题:

func init MyFunctionProj
cd MyFunctionProj
func new --name MyHttpTrigger --template "HttpTrigger"

然后更改 http 触发器以返回一个内部带有枚举的对象。

我的版本:

> func --version
3.0.1975
> dotnet --version
3.1.100

附加信息

我尝试了多种解决方法,所以这里是我的一些观察结果。OkObjectResult由处理对象结果执行器。我尝试将实现复制到我的解决方案中并将其添加到 DI 容器中,以便我可以调试:

builder.Services.AddSingleton<IActionResultExecutor<ObjectResult>, TestExecutor>();

在链接源的第 101 行,选择了格式化程序。有趣的是,当我此时中断时,选择的格式化程序是NewtonsoftJsonOutputFormatter!我会认为第一个JsonConverter-attribute 应该适用于此,但事实并非如此。

我认为修改可用输出格式化程序的列表是值得的。 ActionResultExecutor 使用默认输出格式选择器做出选择,然后注入IOptions<MvcOptions>获取输出格式化程序。

为了强制DefaultOutputFormatterSelector为了做出不同的选择,我尝试了以下方法:

class MvcOptionsConfiguration : IPostConfigureOptions<MvcOptions> 
{
...
}

public class Startup : FunctionsStartup
{
    public override void Configure(IFunctionsHostBuilder builder)
    {
        builder.Services.ConfigureOptions<MvcOptionsConfiguration>();
    }
}

请注意,常规IConfigureOptions<T>不能用作options.Outputformatters- 集合缺少除Microsoft.AspNetCore.Mvc.WebApiCompatShim.HttpResponseMessageOutputFormatter,这本身很奇怪(为什么一个全新的 3.0 应用程序使用兼容性填充程序?)。

我尝试删除类型NewtonsoftJsonOutputFormatter从集合中使用:

options.OutputFormatters.RemoveType<NewtonsoftJsonOutputFormatter>();

为此,我必须引用 nuget 包Microsoft.AspNetCore.Mvc.NewtonsoftJson访问该类型,但我引用它时的类型与运行时使用的类型不同。type.Assembly.CodeBase运行时使用的类型位于%USERPROFILE%/AppData/Local/AzureFunctionsTools/但来自 nuget 的那个位于Project root/bin/Debug。我以前从未遇到过这种情况。通常,该包将是暂时的依赖项,因此我可以引用它而无需明确依赖该包自己,所以我不太确定这里发生了什么。这是正常现象还是我的环境有问题?

当我以另一种方式删除它时,它并不重要,而且无论如何它都会被选中,所以看起来就像MvcOptions注入DefaultOutputFormatterSelector不一样MvcOptions我们可以在启动时进行配置。

此时,我已经没有线索了,于是转向你们。我希望有人能指出我正确的方向。


我能够使用以下代码使其工作

using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json.Converters;

[assembly: FunctionsStartup(typeof(Configs.Startup))]

namespace Configs
{
    class Startup : FunctionsStartup
    {
       public override void Configure(IFunctionsHostBuilder builder)
        {
            builder.Services.AddMvcCore().AddNewtonsoftJson(x =>
            {
                x.SerializerSettings.Converters.Add(new StringEnumConverter());
            });
        }
    }
}

这是在 Azure Functions Core Tools 上的 netcoreapp3.1(3.0.2534 提交哈希:bc1e9efa8fa78dd1a138dd1ac1ebef97aac8d78e)和 Function Runtime 版本:3.0.13353.0 中,包含以下包:

<PackageReference Include="AsyncEnumerator" Version="4.0.2" />
<PackageReference Include="AzureFunctions.Autofac" Version="4.0.0" />
<PackageReference Include="CsvHelper" Version="15.0.5" />
<PackageReference Include="Dapper" Version="2.0.35" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.4" />
<PackageReference Include="Microsoft.Azure.Functions.Extensions" Version="1.0.0" />
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="3.0.7" />
<PackageReference Include="System.Data.SqlClient" Version="4.8.1" />

希望这对某人有帮助。

我在这里推出了一个示例存储库:https://github.com/rawrspace/string-enum-example

编辑:我今天再次使用相同的设置并使用 [JsonConverter(typeof(StringEnumConverter))] 工作得很好。我不确定最近是否发生了更新,但为了以防万一,我将保留上述解决方案。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Azure Functions 3.0 中的属性将 Enum 序列化为字符串 的相关文章

随机推荐