Skip to content

Commit 60a7206

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

File tree

4 files changed

+61
-3
lines changed

4 files changed

+61
-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: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
using JetBrains.Annotations;
2+
using Microsoft.OpenApi.Interfaces;
3+
using Microsoft.OpenApi.Models;
4+
using Microsoft.OpenApi.Services;
5+
using Swashbuckle.AspNetCore.SwaggerGen;
6+
7+
namespace JsonApiDotNetCore.OpenApi;
8+
9+
/// <summary>
10+
/// Removes unreferenced component schemas from the OpenAPI document.
11+
/// </summary>
12+
[UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)]
13+
internal sealed class UnusedComponentSchemaCleaner : IDocumentFilter
14+
{
15+
public void Apply(OpenApiDocument document, DocumentFilterContext context)
16+
{
17+
var visitor = new OpenApiReferenceVisitor();
18+
var walker = new OpenApiWalker(visitor);
19+
walker.Walk(document);
20+
21+
HashSet<string> unusedSchemaNames = [];
22+
23+
foreach (string schemaId in document.Components.Schemas.Select(schema => schema.Key).Where(schemaId => !visitor.UsedSchemaNames.Contains(schemaId)))
24+
{
25+
unusedSchemaNames.Add(schemaId);
26+
}
27+
28+
foreach (string schemaId in unusedSchemaNames)
29+
{
30+
document.Components.Schemas.Remove(schemaId);
31+
}
32+
}
33+
34+
private sealed class OpenApiReferenceVisitor : OpenApiVisitorBase
35+
{
36+
private const string ComponentSchemaPrefix = "#/components/schemas/";
37+
38+
public HashSet<string> UsedSchemaNames { get; } = [];
39+
40+
public override void Visit(IOpenApiReferenceable referenceable)
41+
{
42+
UsedSchemaNames.Add(referenceable.Reference.Id);
43+
}
44+
45+
public override void Visit(OpenApiSchema schema)
46+
{
47+
if (schema.Discriminator != null)
48+
{
49+
foreach (string discriminatorValue in schema.Discriminator.Mapping.Values)
50+
{
51+
if (discriminatorValue.StartsWith(ComponentSchemaPrefix, StringComparison.Ordinal))
52+
{
53+
string schemaId = discriminatorValue[ComponentSchemaPrefix.Length..];
54+
UsedSchemaNames.Add(schemaId);
55+
}
56+
}
57+
}
58+
}
59+
}
60+
}

0 commit comments

Comments
 (0)