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

Swashbuckle OpenAPI3动态模型无需编译的示例与描述配置问题

问题解答

问题1:能否直接通过OpenAPI规范定义模型,不需要通过C#编译器处理?

完全可以。OpenAPI本身是语言无关的接口描述规范,Swagger/OpenAPIDotNet库原生支持直接操作OpenApiDocument对象的结构,不需要依赖编译后的C#实体类生成Schema。你可以直接构造符合OpenAPI规范的OpenApiSchema对象,添加到文档的Components.Schemas节点即可,完全可以替换掉动态编译C#类的方案。

问题2:如何在IDocumentFilter中通过Schema/Paths节点实现示例和描述的展示?

你可以直接在Apply方法中注释的//Add Schema components位置,遍历你从JSON文件读取的所有模型元数据,手动构造OpenApiSchema对象并赋值描述、示例属性,再加入到全局Schema集合中即可。如果需要关联到具体接口的请求/响应,直接修改Paths节点下对应操作的请求体、响应体的Schema引用即可。

以下是完整的补充代码示例:

public void Apply(OpenApiDocument document, DocumentFilterContext context)
{
    // 原有代码保持不变
    if (document.Info.Extensions == null || !document.Info.Extensions.ContainsKey(SwaggerEndpoint.ExtensionDocName)) return;

    var openIdString = document.Info.Extensions[SwaggerEndpoint.ExtensionDocName] as OpenApiString;
    if (openIdString == null) return;

    var docName = openIdString.Value;

    SwaggerEndpoint endpoint = _swaggerDocument.SwaggerEndpoints.SingleOrDefault(x => x.Name == docName);
    if (endpoint == null) return;

    document.Servers = endpoint.ServerObjects;
    document.Tags = endpoint.Tags;

    var pathsObjects = _swaggerDocument.GetPathsObject(docName, context);
    if (pathsObjects.IsValid())
    {
        pathsObjects.ToList().ForEach(
            item => document.Paths.Add(item.Key, item.Value)
            );
    }

    // ========== 以下为新增代码 ==========
    // 初始化Components和Schemas节点
    document.Components ??= new OpenApiComponents();
    document.Components.Schemas ??= new Dictionary<string, OpenApiSchema>();

    // 这里替换为你从JSON读取的模型集合
    var allModels = Models;
    foreach (var model in allModels)
    {
        var modelSchema = new OpenApiSchema
        {
            Type = "object",
            // 如果有模型级别的描述可以在此赋值
            Description = model.Data?.Description,
            Properties = new Dictionary<string, OpenApiSchema>()
        };

        foreach (var p in model.Data.Properties)
        {
            if (p.Obsoleted) continue;

            var propertySchema = new OpenApiSchema();
            // 处理属性类型
            if (p.Type.Type == "array")
            {
                propertySchema.Type = "array";
                propertySchema.Items = new OpenApiSchema
                {
                    Reference = new OpenApiReference
                    {
                        Type = ReferenceType.Schema,
                        Id = p.Type.ArrayType.ObjectName
                    }
                };
            }
            else
            {
                // 基础类型映射,可根据你实际用到的类型扩展
                propertySchema.Type = p.Type.ObjectName.ToLower() switch
                {
                    "string" => "string",
                    "int" => "integer",
                    "int32" => "integer",
                    "int64" => "integer",
                    "bool" => "boolean",
                    "boolean" => "boolean",
                    "float" => "number",
                    "double" => "number",
                    "decimal" => "number",
                    // 自定义对象类型
                    _ => "object"
                };

                // 自定义对象类型添加Schema引用
                if (propertySchema.Type == "object" && p.Type.ObjectName != "object")
                {
                    propertySchema.Reference = new OpenApiReference
                    {
                        Type = ReferenceType.Schema,
                        Id = p.Type.ObjectName
                    };
                }
            }

            // 赋值属性描述
            if (!string.IsNullOrWhiteSpace(p.Description?.ToString()))
            {
                propertySchema.Description = p.Description.ToString();
            }

            // 赋值属性示例,注意要和属性类型匹配
            if (!string.IsNullOrWhiteSpace(p.Example?.ToString()))
            {
                var exampleValue = p.Example.ToString();
                propertySchema.Example = propertySchema.Type switch
                {
                    "string" => new OpenApiString(exampleValue),
                    "integer" => int.TryParse(exampleValue, out var intVal) ? new OpenApiInteger(intVal) : new OpenApiString(exampleValue),
                    "boolean" => bool.TryParse(exampleValue, out var boolVal) ? new OpenApiBoolean(boolVal) : new OpenApiString(exampleValue),
                    "number" => decimal.TryParse(exampleValue, out var decVal) ? new OpenApiDouble((double)decVal) : new OpenApiString(exampleValue),
                    _ => new OpenApiString(exampleValue)
                };
            }

            modelSchema.Properties.Add(p.Name, propertySchema);
        }

        // 避免重复添加
        if (!document.Components.Schemas.ContainsKey(model.Name))
        {
            document.Components.Schemas.Add(model.Name, modelSchema);
        }
    }

    // ========== 如果需要关联到Paths节点的接口,参考以下代码 ==========
    // 示例:给某个POST接口指定请求体Schema
    // if (document.Paths.TryGetValue("/api/your/interface/path", out var pathItem))
    // {
    //     if (pathItem.Operations.TryGetValue(OperationType.Post, out var postOp))
    //     {
    //         postOp.RequestBody = new OpenApiRequestBody
    //         {
    //             Content = new Dictionary<string, OpenApiMediaType>
    //             {
    //                 ["application/json"] = new OpenApiMediaType
    //                 {
    //                     Schema = new OpenApiSchema
    //                     {
    //                         Reference = new OpenApiReference { Type = ReferenceType.Schema, Id = "你的模型名称" }
    //                     }
    //                 }
    //             }
    //         };
    //     }
    // }
}

注意事项

  • 如果你的模型存在循环引用,需要额外处理避免构造Schema时出现死循环
  • 基础类型的映射需要根据你实际用到的类型做完整覆盖,避免Schema类型错误
  • 示例值的类型要和Schema的Type属性匹配,否则Swagger页面可能出现展示异常

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.22 06:15:07