[英]Is it possible to generate referenced schema for oneof properties using Swashbuckle?
默認情況下, Swashbuckle為oneof屬性(universeCategory)生成一個內聯模式,如下所示。
"Universe":{
"type":"object",
"properties":{
"universeCategory":{
"oneOf":[
{
"$ref":"#/components/schemas/FullUniverse"
},
{
"$ref":"#/components/schemas/HalfUniverse"
}
],
"discriminator":{
"propertyName":"source",
"mapping":{
"FullUniverse":"#/components/schemas/FullUniverse",
"HalfUniverse":"#/components/schemas/HalfUniverse"
}
}
}
}
}
是否可以通過將一些配置傳遞給Swashbuckle來生成如下所示的引用模式?
"Universe":{
"type":"object",
"properties":{
"universe":{
"$ref":"#/components/schemas/UniverseCategory"
}
},
"additionalProperties":false
},
"UniverseCategory":{
"oneOf":[
{
"$ref":"#/components/schemas/HalfUniverse"
},
{
"$ref":"#/components/schemas/FullUniverse"
}
],
"discriminator":{
"propertyName":"source",
"mapping":{
"HalfUniverse":"#/components/schemas/HalfUniverse",
"FullUniverse":"#/components/schemas/FullUniverse"
}
}
}
Open API 生成器等工具目前僅支持上述格式。 因此,任何為oneof屬性生成引用模式的解決方法都值得贊賞。
我們可以添加一個自定義過濾器來將 oneof 模式的生成作為單獨的模式來處理,並且可以添加對生成的新模式的引用。
public class HandleOneOfPropertiesFilter : ISchemaFilter
{
public void Apply(OpenApiSchema schema, SchemaFilterContext context)
{
if (schema?.Properties == null || context.Type == null)
{
return;
}
var propertiesWithOneOfHandling = context.Type.GetProperties()
.Where(t => t.GetCustomAttributes().Any(c => c.GetType() == typeof(HandleOneOfPropertiesAttribute)));
foreach (var selectedProps in propertiesWithOneOfHandling)
{
foreach (var props in schema.Properties)
{
if (selectedProps.Name.Equals(props.Key, StringComparison.InvariantCultureIgnoreCase))
{
var oneOfProperty = (HandleOneOfPropertiesAttribute)context.Type.GetProperty(selectedProps.Name)
.GetCustomAttribute(typeof(HandleOneOfPropertiesAttribute));
var name = oneOfProperty.Prefix + selectedProps.Name;
if (props.Value.Type == "array")
{
// Handling array type differently
context.SchemaRepository.Schemas.Add(name, props.Value.Items);
var newSchema = new OpenApiSchema();
newSchema.Type = "array";
newSchema.Items = new OpenApiSchema
{
Reference = new OpenApiReference
{
Id = name,
Type = ReferenceType.Schema
}
};
context.SchemaRepository.Schemas.Add(name + "Array", newSchema);
props.Value.Reference = new OpenApiReference
{
Id = name + "Array",
Type = ReferenceType.Schema
};
}
else
{
context.SchemaRepository.Schemas.Add(name, props.Value);
props.Value.Reference = new OpenApiReference
{
Id = name,
Type = ReferenceType.Schema
};
}
}
}
}
}
}
然后我們需要定義一個屬性來確定我們需要在哪些屬性上處理生成,讓我們創建屬性
public class HandleOneOfPropertiesAttribute : Attribute
{
public HandleOneOfPropertiesAttribute(string prefix)
{
Prefix = prefix;
}
public string Prefix { get; }
}
然后我們需要將此屬性用於 model 的 oneof 類型的屬性。 在下面的代碼片段中,我使用了“OneOfProp”前綴,因此生成的新模式將具有此前綴
public class ModelClass
{
[HandleOneOfProperties("OneOfProp")]
public Universe property1 { get; set; }
[HandleOneOfProperties("OneOfProp")]
public Galaxy property2 { get; set; }
}
最后在服務中注冊這個過濾器
services.AddSwaggerGen(c =>
{
c.SchemaFilter<HandleOneOfPropertiesFilter>();
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.