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

Azure Function OpenApi规范下生成带OneOf标识的具体类问题咨询

实现方案

以下方案基于微软官方Microsoft.Azure.WebJobs.Extensions.OpenApi包扩展实现,无需依赖停止维护的社区适配包,通过自定义过滤器完成OneOf规则注入。

前置依赖

先安装官方NuGet包:

  • 进程内模型:Microsoft.Azure.WebJobs.Extensions.OpenApi
  • 隔离工作进程模型:Microsoft.Azure.Functions.Worker.Extensions.OpenApi

步骤1:自定义OneOf标记属性

用于标注需要生成多态结构的接口属性,指定实现类和鉴别器字段:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class OneOfAttribute : Attribute
{
    /// <summary>
    /// 鉴别器属性名
    /// </summary>
    public string DiscriminatorProperty { get; }
    /// <summary>
    /// 接口的所有实现类类型
    /// </summary>
    public Type[] ImplementTypes { get; }

    public OneOfAttribute(string discriminatorProperty, params Type[] implementTypes)
    {
        DiscriminatorProperty = discriminatorProperty;
        ImplementTypes = implementTypes;
    }
}

给你的返回类属性标记该特性:

public class PersonResponse
{
    public string Id { get; set; }
    // 如果需要数组格式,把属性改为IPersonData[] Data即可
    [OneOf(nameof(IPersonData.PersonType), typeof(PersonA), typeof(PersonB))]
    public IPersonData Data { get; set; }
}

步骤2:实现自定义Schema过滤器

通过OpenApi的扩展点ISchemaFilter注入OneOf规则:

using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Abstractions;
using Microsoft.OpenApi.Models;
using System.Reflection;

public class OneOfSchemaFilter : ISchemaFilter
{
    public void Apply(OpenApiSchema schema, SchemaFilterContext context)
    {
        if (context.MemberInfo is not PropertyInfo propInfo) return;
        
        var oneOfAttr = propInfo.GetCustomAttribute<OneOfAttribute>();
        if (oneOfAttr == null) return;

        // 如果是集合类型,按你期望的数组格式生成
        var propType = propInfo.PropertyType;
        bool isCollection = propType.IsArray || (propType.IsGenericType && typeof(IEnumerable<>).IsAssignableFrom(propType.GetGenericTypeDefinition()));

        if (isCollection)
        {
            schema.Type = "array";
            schema.Items = new OpenApiSchema
            {
                OneOf = new List<OpenApiSchema>(),
                Discriminator = new OpenApiDiscriminator
                {
                    PropertyName = oneOfAttr.DiscriminatorProperty
                }
            };

            foreach (var implType in oneOfAttr.ImplementTypes)
            {
                var implSchema = context.SchemaGenerator.GenerateSchema(implType, context.SchemaRepository);
                schema.Items.OneOf.Add(new OpenApiSchema { Reference = implSchema.Reference });
                
                if (!context.SchemaRepository.Schemas.ContainsKey(implType.Name))
                {
                    context.SchemaRepository.Schemas.Add(implType.Name, implSchema);
                }
            }
        }
        // 单个对象场景
        else
        {
            schema.Type = "object";
            schema.OneOf = new List<OpenApiSchema>();
            schema.Discriminator = new OpenApiDiscriminator
            {
                PropertyName = oneOfAttr.DiscriminatorProperty
            };

            foreach (var implType in oneOfAttr.ImplementTypes)
            {
                var implSchema = context.SchemaGenerator.GenerateSchema(implType, context.SchemaRepository);
                schema.OneOf.Add(new OpenApiSchema { Reference = implSchema.Reference });
                
                if (!context.SchemaRepository.Schemas.ContainsKey(implType.Name))
                {
                    context.SchemaRepository.Schemas.Add(implType.Name, implSchema);
                }
            }
        }
    }
}

步骤3:注册过滤器到OpenApi配置

进程内Azure Functions

在Startup类中注册:

public override void Configure(IFunctionsHostBuilder builder)
{
    builder.Services.AddSingleton<ISchemaFilter, OneOfSchemaFilter>();
    
    builder.AddOpenApi(options =>
    {
        options.Version = "0.1";
        options.Title = "API";
    });
}

隔离工作进程Azure Functions

在Program.cs中注册:

var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults()
    .ConfigureOpenApi()
    .ConfigureServices(services =>
    {
        services.AddSingleton<ISchemaFilter, OneOfSchemaFilter>();
    })
    .Build();

host.Run();

验证生成结果

启动Azure Functions项目后访问OpenApi端点,生成的规范会自动包含你需要的oneOf和discriminator配置,和期望输出完全匹配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 03:57:02