【问题标题】:Swashbuckle Hide unreferenced modelSwashbuckle 隐藏未引用的模型
【发布时间】:2022-03-29 02:45:41
【问题描述】:

我在隐藏调用时遇到了 Swashbuckle 问题,链接到调用的模型的定义仍保留在生成的 JSON 中的定义中。

使用文档过滤器,我可以从界面中删除调用。

调用保留在生成的 JSON 中,但在 Swagger UI 中不可见。 我们还可以看到链接到这些调用的 Model 和 Enum 的定义。

这些是内部调用,需要在 JSON 中对外部眼睛隐藏。

如何隐藏所有调用及其引用?

使用 [ApiExplorerSettings(IgnoreApi = true)] 可以解决我的问题,但我需要使用现有属性进行过滤。

【问题讨论】:

    标签: swashbuckle


    【解决方案1】:

    所以我通过努力找到了我的问题的答案。 我把它放在这里是为了让下一个遇到我问题的人过得比我好。

    public static class SwashbuckleExtensions
    {
        public static IEnumerable<Operation> EnumerateOperations(this PathItem pathItem)
        {
            if (pathItem == null)
            {
                yield break;
            }
            yield return pathItem.get;
            yield return pathItem.post;
            yield return pathItem.put;
            yield return pathItem.delete;
            yield return pathItem.options;
            yield return pathItem.head;
        }
    
    
        public static IEnumerable<Schema> EnumerateSchema(this Operation operation)
        {
            if (operation == null)
            {
                yield break;
            }
                       foreach (var response in operation.responses ?? new Dictionary<string, Response>())
            {
                yield return response.Value.schema;
                if (response.Value.schema.items != null)
                {
                    yield return response.Value.schema.items;
                }
            }
            foreach (var parameter in operation.parameters ?? new List<Parameter>())
            {
                yield return parameter.schema;
            }
        }
    
    
        public static IEnumerable<Schema> FindAdditionalSchema(this Schema schema, IDictionary<string, Schema> listOfDefinition)
        {
            if (!string.IsNullOrEmpty(schema.@ref))
            {
                Schema definition;
                if (listOfDefinition.TryGetValue(schema.@ref.Replace("#/definitions/", String.Empty), out definition))
                {
                    foreach (var propertySchema in definition.properties)
                    {
                        yield return propertySchema.Value;
                    }
                }
            }
            if (!string.IsNullOrEmpty( schema?.items?.@ref))
            {
                Schema definition;
                if (listOfDefinition.TryGetValue(schema.items.@ref.Replace("#/definitions/", String.Empty), out definition))
                {
                    foreach (var propertySchema in definition.properties)
                    {
                        yield return propertySchema.Value;
                    }
                }
            }
        }
    
        public static IEnumerable<Schema> EnumerateSchema(this Schema schema,IDictionary<string,Schema> listOfDefinition, int dept = 0)
        {
            if (schema == null)
            {
                yield break;
            }
            if (dept > 10)
            {
                yield break;
            }
            if (dept == 0)
            {
                yield return schema;
            }
    
            var ListOfAdditionalSchema = schema.FindAdditionalSchema(listOfDefinition) ?? new List<Schema>();
            foreach (var additionalSchema in ListOfAdditionalSchema)
            {
                yield return additionalSchema;
                foreach (var childSchema in additionalSchema.EnumerateSchema(listOfDefinition,dept++) ?? new List<Schema>())
                {
                    yield return childSchema;
                }
            }
           }
    }
    

    然后在 DocumentFilter 中

        public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer)
            {
    
    
                foreach (var value in swaggerDoc.paths.Values)
                {
                    if (value.post != null && value.post.tags.Contains(ToHide))
                        value.post = null;
    
                    if (value.get != null && value.get.tags.Contains(ToHide))
                        value.get = null;
    
                    if (value.put != null && value.put.tags.Contains(ToHide))
                        value.put = null;
    
                    if (value.delete != null && value.delete.tags.Contains(ToHide))
                        value.delete = null;
    
                    if (value.head != null && value.head.tags.Contains(ToHide))
                        value.head = null;
    
                    if (value.options != null && value.options.tags.Contains(ToHide))
                        value.options = null;
                }
    
                var pathToDelete = swaggerDoc.paths.Where(x => !x.Value.EnumerateOperations().Any(y=>y != null) )
                                                   .ToList();//Deleting item from source need list 
                foreach (var item in pathToDelete)
                {
                    swaggerDoc.paths.Remove(item.Key);
                }
    
    
                var listOfSchemaWithReference = swaggerDoc.paths.SelectMany(x => x.Value.EnumerateOperations())//Find operation by path
                                                .SelectMany(x => x.EnumerateSchema()) //Find schema by operation
                                                .SelectMany(x => x.EnumerateSchema(swaggerDoc.definitions))//Find Schema by schema (dependent schema)
                                                .Where(x=> x?.@ref != null || x?.items?.@ref != null)//I only wany the schema that reference a definition.
                                                .Select(x=> ((x?.@ref) ?? (x.items?.@ref) ).Replace("#/definitions/", String.Empty))//remove the path and keep the Model name
                                                .Distinct()//I dont like duplicates
                                                .ToList();//commit to memory
    
                //Not finding a definition in the built list of reference means its unreferenced and can be removed.
                var listOfUnreferencedDefinition = swaggerDoc.definitions.Where(x => !listOfSchemaWithReference.Any(y => y == x.Key))
                                                                         .ToList();//Deleting item from source need list 
    
                foreach (var unreferencedDefinition in listOfUnreferencedDefinition)
                {
                    swaggerDoc.definitions.Remove(unreferencedDefinition.Key);
                }
            }
        }
    

    【讨论】:

    • 这个怎么用?添加 [ToHide] 装饰器?
    • 在我的 SwaggetConfig 我有一个 c.OperationFilter();和 c.DocumentFilter(); protected class ExternalOnlyFilter : IOperationFilter, IDocumentFilter 在 Apply 我在 operation.tags 中设置了 Value ToHide
    【解决方案2】:

    对于上面JM123的回答,

    .EnumerateSchema(listOfDefinition,dept++) 应该是a.EnumerateSchema(listOfDefinition,dept+1)

    由于这是在一个循环中,它在迭代列表时会增加深度,而不仅仅是随着嵌套的深入。使用原始代码,这会开始删除具有大量引用的模型的引用,即使它们没有嵌套。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-28
      • 1970-01-01
      • 1970-01-01
      • 2014-05-04
      相关资源
      最近更新 更多