Skip to content

Commit f7eec8b

Browse files
authored
Add SchemaRepository.ReplaceSchemaId() (#3708)
* Add public method SchemaRepository.ReplaceSchemaId * Review feedback * More review feedback
1 parent 36dbac8 commit f7eec8b

File tree

4 files changed

+141
-2
lines changed

4 files changed

+141
-2
lines changed

Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
3838
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
3939
<UseArtifactsOutput>true</UseArtifactsOutput>
40-
<VersionPrefix>10.0.2</VersionPrefix>
40+
<VersionPrefix>10.1.0</VersionPrefix>
4141
<WarnOnPackingNonPackableProject>false</WarnOnPackingNonPackableProject>
4242
</PropertyGroup>
4343
<PropertyGroup Condition=" '$(GITHUB_ACTIONS)' != '' AND '$(DEPENDABOT_JOB_ID)' == '' ">
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-

1+
Swashbuckle.AspNetCore.SwaggerGen.SchemaRepository.ReplaceSchemaId(System.Type schemaType, string replacementSchemaId) -> bool

src/Swashbuckle.AspNetCore.SwaggerGen/SwaggerGenerator/SchemaRepository.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,24 @@ public OpenApiSchemaReference AddDefinition(string schemaId, OpenApiSchema schem
4242

4343
return new OpenApiSchemaReference(schemaId);
4444
}
45+
46+
public bool ReplaceSchemaId(Type schemaType, string replacementSchemaId)
47+
{
48+
ArgumentNullException.ThrowIfNull(schemaType);
49+
ArgumentException.ThrowIfNullOrEmpty(replacementSchemaId);
50+
51+
if (_reservedIds.TryGetValue(schemaType, out string oldSchemaId) &&
52+
oldSchemaId != replacementSchemaId &&
53+
Schemas.TryGetValue(oldSchemaId, out var targetSchema))
54+
{
55+
if (Schemas.TryAdd(replacementSchemaId, targetSchema))
56+
{
57+
Schemas.Remove(oldSchemaId);
58+
_reservedIds.Remove(schemaType);
59+
return true;
60+
}
61+
}
62+
63+
return false;
64+
}
4565
}
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
using Microsoft.OpenApi;
2+
3+
namespace Swashbuckle.AspNetCore.SwaggerGen.Test;
4+
5+
public static class SchemaRepositoryTests
6+
{
7+
[Fact]
8+
public static void ReplaceSchemaId_ExistingSchema_ReplacesSchemaId()
9+
{
10+
var repository = new SchemaRepository();
11+
(string oldSchemaId, IOpenApiSchema exampleSchema) = GenerateSchemaForType(typeof(Example), repository);
12+
13+
string newSchemaId = "alternateId";
14+
bool result = repository.ReplaceSchemaId(typeof(Example), newSchemaId);
15+
16+
Assert.True(result);
17+
Assert.DoesNotContain(oldSchemaId, repository.Schemas);
18+
Assert.Contains(newSchemaId, repository.Schemas);
19+
Assert.Same(exampleSchema, repository.Schemas[newSchemaId]);
20+
}
21+
22+
[Fact]
23+
public static void ReplaceSchemaId_MultipleSchemas_ReplacesSchemaId()
24+
{
25+
var repository = new SchemaRepository();
26+
(string oldSchemaId, IOpenApiSchema exampleSchema) = GenerateSchemaForType(typeof(Example), repository);
27+
(string otherSchemaId, IOpenApiSchema otherSchema) = GenerateSchemaForType(typeof(Exception), repository);
28+
29+
string newSchemaId = "alternateId";
30+
bool result = repository.ReplaceSchemaId(typeof(Example), newSchemaId);
31+
32+
Assert.True(result);
33+
Assert.DoesNotContain(oldSchemaId, repository.Schemas);
34+
Assert.Contains(newSchemaId, repository.Schemas);
35+
Assert.Same(exampleSchema, repository.Schemas[newSchemaId]);
36+
Assert.Contains(otherSchemaId, repository.Schemas);
37+
Assert.Same(otherSchema, repository.Schemas[otherSchemaId]);
38+
}
39+
40+
[Fact]
41+
public static void ReplaceSchemaId_MissingSchema_DoesNotChange()
42+
{
43+
var repository = new SchemaRepository();
44+
45+
string newSchemaId = "alternateId";
46+
bool result = repository.ReplaceSchemaId(typeof(Example), newSchemaId);
47+
48+
Assert.False(result);
49+
Assert.DoesNotContain(newSchemaId, repository.Schemas);
50+
}
51+
52+
[Fact]
53+
public static void ReplaceSchemaId_UnchangedId_DoesNotChange()
54+
{
55+
var repository = new SchemaRepository();
56+
(string schemaId, IOpenApiSchema exampleSchema) = GenerateSchemaForType(typeof(Example), repository);
57+
58+
bool result = repository.ReplaceSchemaId(typeof(Example), schemaId);
59+
60+
Assert.False(result);
61+
Assert.Contains(schemaId, repository.Schemas);
62+
Assert.Same(exampleSchema, repository.Schemas[schemaId]);
63+
}
64+
65+
[Fact]
66+
public static void ReplaceSchemaId_ExistingId_DoesNotChange()
67+
{
68+
var repository = new SchemaRepository();
69+
70+
var otherSchema = new OpenApiSchema();
71+
string otherSchemaId = "alreadyInUse";
72+
repository.Schemas.Add(otherSchemaId, otherSchema);
73+
74+
GenerateSchemaForType(typeof(Example), repository);
75+
76+
bool result = repository.ReplaceSchemaId(typeof(Example), otherSchemaId);
77+
78+
Assert.False(result);
79+
Assert.Contains(otherSchemaId, repository.Schemas);
80+
Assert.Same(otherSchema, repository.Schemas[otherSchemaId]);
81+
}
82+
83+
[Fact]
84+
public static void ReplaceSchemaId_CanGenerateMultipleTimes()
85+
{
86+
var repository = new SchemaRepository();
87+
GenerateSchemaForType(typeof(Example), repository);
88+
89+
string newSchemaId1 = "exampleVariant1";
90+
bool result1 = repository.ReplaceSchemaId(typeof(Example), newSchemaId1);
91+
Assert.True(result1);
92+
93+
GenerateSchemaForType(typeof(Example), repository);
94+
95+
string newSchemaId2 = "exampleVariant2";
96+
bool result2 = repository.ReplaceSchemaId(typeof(Example), newSchemaId2);
97+
Assert.True(result2);
98+
99+
Assert.Equal(2, repository.Schemas.Count);
100+
Assert.Contains(newSchemaId1, repository.Schemas);
101+
Assert.Contains(newSchemaId2, repository.Schemas);
102+
}
103+
104+
private static (string, IOpenApiSchema) GenerateSchemaForType(Type type, SchemaRepository repository)
105+
{
106+
var generator = new SchemaGenerator(new(), new JsonSerializerDataContractResolver(new()));
107+
var schemaReference = (OpenApiSchemaReference)generator.GenerateSchema(type, repository);
108+
109+
string schemaId = schemaReference.Reference.Id!;
110+
IOpenApiSchema schema = repository.Schemas[schemaId];
111+
112+
return (schemaId, schema);
113+
}
114+
115+
private sealed class Example
116+
{
117+
public string Value { get; set; }
118+
}
119+
}

0 commit comments

Comments
 (0)