Skip to content

Commit cdad1ad

Browse files
committed
Use post-processing step to cleanup unused component schemas
1 parent 66be210 commit cdad1ad

File tree

4 files changed

+59
-3
lines changed

4 files changed

+59
-3
lines changed

src/JsonApiDotNetCore.OpenApi/ConfigureSwaggerGenOptions.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ public void Configure(SwaggerGenOptions options)
4747
options.DocumentFilter<ServerDocumentFilter>();
4848
options.DocumentFilter<EndpointOrderingFilter>();
4949
options.OperationFilter<JsonApiOperationDocumentationFilter>();
50+
options.DocumentFilter<UnusedComponentSchemaCleaner>();
5051
}
5152

5253
private IEnumerable<Type> GetConstructedTypesForResourceData(Type baseType)

src/JsonApiDotNetCore.OpenApi/SwaggerComponents/DocumentSchemaGenerator.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,6 @@ private void SetJsonApiVersion(OpenApiSchema fullSchemaForDocument, SchemaReposi
163163
if (!_options.IncludeJsonApiVersion)
164164
{
165165
fullSchemaForDocument.Properties.Remove(JsonApiPropertyName.Jsonapi);
166-
schemaRepository.Schemas.Remove(jsonapiSchemaId);
167166
}
168167
else
169168
{

src/JsonApiDotNetCore.OpenApi/SwaggerComponents/ResourceDataSchemaGenerator.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,6 @@ private void SetResourceAttributes(OpenApiSchema fullSchemaForResourceData, Reso
125125
if (!fullSchemaForAttributes.Properties.Any())
126126
{
127127
fullSchemaForResourceData.Properties.Remove(JsonApiPropertyName.Attributes);
128-
schemaRepository.Schemas.Remove(referenceSchemaForAttributes.Reference.Id);
129128
}
130129
else
131130
{
@@ -143,7 +142,6 @@ private void SetResourceRelationships(OpenApiSchema fullSchemaForResourceData, R
143142
if (!fullSchemaForRelationships.Properties.Any())
144143
{
145144
fullSchemaForResourceData.Properties.Remove(JsonApiPropertyName.Relationships);
146-
schemaRepository.Schemas.Remove(referenceSchemaForRelationships.Reference.Id);
147145
}
148146
else
149147
{
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
using Microsoft.OpenApi.Interfaces;
2+
using Microsoft.OpenApi.Models;
3+
using Microsoft.OpenApi.Services;
4+
using Swashbuckle.AspNetCore.SwaggerGen;
5+
6+
namespace JsonApiDotNetCore.OpenApi;
7+
8+
/// <summary>
9+
/// Removes unreferenced component schemas from the OpenAPI document.
10+
/// </summary>
11+
internal sealed class UnusedComponentSchemaCleaner : IDocumentFilter
12+
{
13+
public void Apply(OpenApiDocument document, DocumentFilterContext context)
14+
{
15+
var visitor = new OpenApiReferenceVisitor();
16+
var walker = new OpenApiWalker(visitor);
17+
walker.Walk(document);
18+
19+
HashSet<string> unusedSchemaNames = [];
20+
21+
foreach (string schemaId in document.Components.Schemas.Select(schema => schema.Key).Where(schemaId => !visitor.UsedSchemaNames.Contains(schemaId)))
22+
{
23+
unusedSchemaNames.Add(schemaId);
24+
}
25+
26+
foreach (string schemaId in unusedSchemaNames)
27+
{
28+
document.Components.Schemas.Remove(schemaId);
29+
}
30+
}
31+
32+
private sealed class OpenApiReferenceVisitor : OpenApiVisitorBase
33+
{
34+
private const string ComponentSchemaPrefix = "#/components/schemas/";
35+
36+
public HashSet<string> UsedSchemaNames { get; } = [];
37+
38+
public override void Visit(IOpenApiReferenceable referenceable)
39+
{
40+
UsedSchemaNames.Add(referenceable.Reference.Id);
41+
}
42+
43+
public override void Visit(OpenApiSchema schema)
44+
{
45+
if (schema.Discriminator != null)
46+
{
47+
foreach (string discriminatorValue in schema.Discriminator.Mapping.Values)
48+
{
49+
if (discriminatorValue.StartsWith(ComponentSchemaPrefix, StringComparison.Ordinal))
50+
{
51+
string schemaId = discriminatorValue[ComponentSchemaPrefix.Length..];
52+
UsedSchemaNames.Add(schemaId);
53+
}
54+
}
55+
}
56+
}
57+
}
58+
}

0 commit comments

Comments
 (0)