2015-12-21 25 views
6

私はAsp.Net Web API 5.2プロジェクトをC#で作成し、Swashbuckleでドキュメントを生成しています。Swagger APIドキュメントにSwashbuckleを使用してサブクラスを含めるにはどうすればよいですか?

私は、Animal抽象クラスのAnimalプロパティとそこから派生するDogクラスとCatクラスのような継承を含むモデルを持っています。

SwashbuckleはAnimalクラスのスキーマしか示していないので、私はISchemaFilter(これも彼らが示唆していること)を試してみましたが、動作させることができず、適切な例も見つけられませんでした。

誰でも助けることができますか?

+0

どれでも運がこれを把握:前のコードはポリモーフィズムのサポートのセクション」のモデルで、hereを指定された実装は何

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); } } 

これは、基本的には次のようなものを作り出します出る? – Craig

+0

まだもう一度それを調べなければならないでしょう。 –

答えて

13

Swashbuckleはポリモーフィズムを正しく実装していないようですが、私はサブクラスについての作者の考え方をパラメータとして理解しています(もし、アクションがAnimalクラスを期待し、dogオブジェクトまたはcatオブジェクト2つの異なるアクションが必要です。)しかし、戻り値の型としてAnimalを返すのは正しいと考えられ、オブジェクトはDogまたはCat型になる可能性があります。

私のAPIを記述し、正しいguidlinesに沿って適切なJSONスキーマを生成するには(自分でディスクリミネータを記述する方法には注意してください。独自のディスクリミネータがあれば、特にその部分を変更する必要があります)次のように文書とスキーマフィルタは:。

{ 
    "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" 
      ] 
     } 
     ] 
    } 
    } 
} 
+2

'SchemaIdProvider'は自分のクラスでなければなりませんか? Swaggerのデフォルトの規約では、Swashbuckle.Swaggerを使ってコードラインを 'var parentSchema = schemaRegistry.Definitions [abstractType.FriendlyId];に変更することができます。 – wags1999

+0

はい、それは私のクラスです。 schemaIdのデリゲートもあるので、私はそれが必要です:configuration.SchemaId(SchemaIdProvider.GetSchemaId); –

+2

@PaoloVigori:Swashbuckle.AspNetCoreでは、PolymorphismDocumentFilterが呼び出され、コードには識別子が設定されていますが、生成されたスワッガー定義には使用されていません。 'allOf'エントリはそこにあります。何か案は? – Tseng

関連する問題