我怎样包括使用Swashbuckle扬鞭API文档中的子类? [英] How do I include subclasses in Swagger API documentation using Swashbuckle?

查看:1076
本文介绍了我怎样包括使用Swashbuckle扬鞭API文档中的子类?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在C#中Asp.Net的Web API 5.2项目,并生成文档与Swashbuckle。

I have an Asp.Net web API 5.2 project in c# and generating documentation with Swashbuckle.

我有一个包含继承像从动物抽象类,狗和猫类,从中获得具有动物属性模型。

I have model that contain inheritance something like having an Animal property from an Animal abstract class and Dog and Cat classes that derive from it.

Swashbuckle只显示了动物类的架构,所以我试着用ISchemaFilter(他们有什么建议太),但我不能让它工作,我也无法找到一个合适的例子。

Swashbuckle only shows the schema for the Animal class so I tried to play with ISchemaFilter (that what they suggest too) but I couldn't make it work and also I cannot find a proper example.

任何人都可以帮忙吗?

Anybody can help?

推荐答案

这似乎Swashbuckle不正确地实现多态性与我明白笔者看有关的子类作为参数的点(如果一个动作expectes的动物类和行为不同,如果你与狗对象或猫对象调用它,那么你应该有2个不同的动作..)但返回类型,我相信这是正确的返回动物和物体可能是狗或猫的类型。

It seems Swashbuckle doesn't implement polymorphism correctly and I understand the point of view of the author about subclasses as parameters (if an action expectes an Animal class and behave differently if you call it with a dog object or a cat object, then you should have 2 different actions..) but as return types I believe that it is correct to return Animal and the objects could be Dog or Cat types.

所以来形容我的API,并产生具有正确guidlines(注意我描述disciminator的方式,如果你有自己的鉴别,你可能需要更改特别是一部分)行适当的JSON模式中,我使用的文件和模式滤波器如下:

So to describe my API and produce a proper JSON schema in line with correct guidlines (be aware of the way I describe the disciminator, if you have your own discriminator you may need to change that part in particular), I use document and schema filters as follow:

SwaggerDocsConfig configuration;
.....
configuration.DocumentFilter<PolymorphismDocumentFilter<YourBaseClass>>();
configuration.SchemaFilter<PolymorphismSchemaFilter<YourBaseClass>>();
.....

public class PolymorphismSchemaFilter<T> : ISchemaFilter
{
    private readonly Lazy<HashSet<Type>> derivedTypes = new Lazy<HashSet<Type>>(Init);

    private static HashSet<Type> Init()
    {
        var abstractType = typeof(T);
        var dTypes = abstractType.Assembly
                                 .GetTypes()
                                 .Where(x => abstractType != x && abstractType.IsAssignableFrom(x));

        var result = new HashSet<Type>();

        foreach (var item in dTypes)
            result.Add(item);

        return result;
    }

    public void Apply(Schema schema, SchemaRegistry schemaRegistry, Type type)
    {
        if (!derivedTypes.Value.Contains(type)) return;

        var clonedSchema = new Schema
                                {
                                    properties = schema.properties,
                                    type = schema.type,
                                    required = schema.required
                                };

        //schemaRegistry.Definitions[typeof(T).Name]; does not work correctly in SwashBuckle
        var parentSchema = new Schema { @ref = "#/definitions/" + typeof(T).Name };   

        schema.allOf = new List<Schema> { parentSchema, clonedSchema };

        //reset properties for they are included in allOf, should be null but code does not handle it
        schema.properties = new Dictionary<string, Schema>();
    }
}

public class PolymorphismDocumentFilter<T> : IDocumentFilter
{
    public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, System.Web.Http.Description.IApiExplorer apiExplorer)
    {
        RegisterSubClasses(schemaRegistry, typeof(T));
    }

    private static void RegisterSubClasses(SchemaRegistry schemaRegistry, Type abstractType)
    {
        const string discriminatorName = "discriminator";

        var parentSchema = schemaRegistry.Definitions[SchemaIdProvider.GetSchemaId(abstractType)];

        //set up a discriminator property (it must be required)
        parentSchema.discriminator = discriminatorName;
        parentSchema.required = new List<string> { discriminatorName };

        if (!parentSchema.properties.ContainsKey(discriminatorName))
            parentSchema.properties.Add(discriminatorName, new Schema { type = "string" });

        //register all subclasses
        var derivedTypes = abstractType.Assembly
                                       .GetTypes()
                                       .Where(x => abstractType != x && abstractType.IsAssignableFrom(x));

        foreach (var item in derivedTypes)
            schemaRegistry.GetOrRegister(item);
    }
}

在previous code农具指定什么这里,在部分机型。多态性支持它基本上会产生类似以下内容:

What the previous code implements is specified here, in the section "Models with Polymorphism Support. It basically produces something like the following:

{
  "definitions": {
    "Pet": {
      "type": "object",
      "discriminator": "petType",
      "properties": {
        "name": {
          "type": "string"
        },
        "petType": {
          "type": "string"
        }
      },
      "required": [
        "name",
        "petType"
      ]
    },
    "Cat": {
      "description": "A representation of a cat",
      "allOf": [
        {
          "$ref": "#/definitions/Pet"
        },
        {
          "type": "object",
          "properties": {
            "huntingSkill": {
              "type": "string",
              "description": "The measured skill for hunting",
              "default": "lazy",
              "enum": [
                "clueless",
                "lazy",
                "adventurous",
                "aggressive"
              ]
            }
          },
          "required": [
            "huntingSkill"
          ]
        }
      ]
    },
    "Dog": {
      "description": "A representation of a dog",
      "allOf": [
        {
          "$ref": "#/definitions/Pet"
        },
        {
          "type": "object",
          "properties": {
            "packSize": {
              "type": "integer",
              "format": "int32",
              "description": "the size of the pack the dog is from",
              "default": 0,
              "minimum": 0
            }
          },
          "required": [
            "packSize"
          ]
        }
      ]
    }
  }
}

这篇关于我怎样包括使用Swashbuckle扬鞭API文档中的子类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆