Skip to content

Commit 3486a02

Browse files
committed
feat: Added OpenApiDocument Simplify extension.
1 parent 307801a commit 3486a02

File tree

2 files changed

+116
-0
lines changed

2 files changed

+116
-0
lines changed

src/libs/OpenApiGenerator.Core/Extensions/OpenApiExtensions.cs

+103
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1+
using System.Collections.Immutable;
12
using System.Globalization;
3+
using Microsoft.OpenApi;
24
using Microsoft.OpenApi.Any;
5+
using Microsoft.OpenApi.Extensions;
36
using Microsoft.OpenApi.Interfaces;
47
using Microsoft.OpenApi.Models;
58
using Microsoft.OpenApi.Readers;
@@ -34,6 +37,106 @@ public static OpenApiDocument GetOpenApiDocument(
3437
return openApiDocument;
3538
}
3639

40+
public static OpenApiDocument Simplify(
41+
this OpenApiDocument openApiDocument)
42+
{
43+
openApiDocument = openApiDocument ?? throw new ArgumentNullException(nameof(openApiDocument));
44+
45+
var schemasToRemove = new List<KeyValuePair<string, OpenApiSchema>>();
46+
var schemasToAdd = new List<KeyValuePair<string, OpenApiSchema>>();
47+
foreach (var schema in openApiDocument.Components.Schemas)
48+
{
49+
// If schema is OneOf and all children have only one enum value, combine them into one schema.
50+
if (schema.Value.IsOneOf() &&
51+
schema.Value.OneOf.All(child =>
52+
child.Properties.Any(subChild =>
53+
subChild.Value.IsEnum() &&
54+
subChild.Value.Enum.Count == 1)))
55+
{
56+
var subChildren = schema.Value.OneOf
57+
.Select(child =>
58+
child.Properties.First(subChild =>
59+
subChild.Value.IsEnum() &&
60+
subChild.Value.Enum.Count == 1))
61+
.ToList();
62+
var newEnum = new OpenApiSchema
63+
{
64+
Enum = subChildren
65+
.Select(x => x.Value.Enum.First())
66+
.ToArray(),
67+
Type = "string",
68+
}.WithKey(schema.Key.ToPropertyName() + subChildren.First().Key.ToPropertyName());
69+
schemasToAdd.Add(newEnum);
70+
71+
foreach (var child in schema.Value.OneOf)
72+
{
73+
var subChild = child.Properties.First(subChild =>
74+
subChild.Value.IsEnum() &&
75+
subChild.Value.Enum.Count == 1);
76+
child.Properties.Remove(subChild);
77+
var newSubChild = new KeyValuePair<string, OpenApiSchema>(
78+
subChild.Key,
79+
new OpenApiSchema
80+
{
81+
Reference = new OpenApiReference
82+
{
83+
Id = newEnum.Key,
84+
Type = ReferenceType.Schema,
85+
},
86+
});
87+
child.Properties.Add(newSubChild);
88+
89+
newSubChild.Value.Extensions["x-original-schema"] = new OpenApiString(
90+
subChild.Value.SerializeAsYaml(OpenApiSpecVersion.OpenApi3_0));
91+
}
92+
93+
// Remove duplicated schemas from OneOf.
94+
// Skip schemas with references.
95+
if (schema.Value.OneOf.Any(x => x.Reference == null))
96+
{
97+
var duplicatedSchemas = new List<OpenApiSchema>();
98+
foreach (var group in schema.Value.OneOf
99+
.GroupBy(x => x.Properties
100+
.Select(y => (y.Key, y.Value.Type, y.Value.Format, y.Value.Reference?.Id))
101+
.ToImmutableArray().AsEquatableArray())
102+
.Where(x => x.Count() > 1))
103+
{
104+
var first = group.First();
105+
foreach (var schemaToRemove in group.Skip(1))
106+
{
107+
first.Description += $"\n{schemaToRemove.Description}";
108+
duplicatedSchemas.Add(schemaToRemove);
109+
}
110+
}
111+
112+
foreach (var duplicatedSchema in duplicatedSchemas)
113+
{
114+
schema.Value.OneOf.Remove(duplicatedSchema);
115+
}
116+
}
117+
118+
// Simplify OneOf with only one schema.
119+
if (schema.Value.OneOf.Count == 1)
120+
{
121+
schemasToRemove.Add(schema);
122+
schemasToAdd.Add(new KeyValuePair<string, OpenApiSchema>(
123+
schema.Key,
124+
schema.Value.OneOf.First()));
125+
}
126+
}
127+
}
128+
foreach (var schema in schemasToRemove)
129+
{
130+
openApiDocument.Components.Schemas.Remove(schema);
131+
}
132+
foreach (var schema in schemasToAdd)
133+
{
134+
openApiDocument.Components.Schemas.Add(schema);
135+
}
136+
137+
return openApiDocument;
138+
}
139+
37140
/// <summary>
38141
/// https://swagger.io/docs/specification/describing-parameters/
39142
/// https://swagger.io/docs/specification/serialization/

src/libs/OpenApiGenerator.Core/Helpers/SmartNamedAnyOfNames.cs

+13
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,19 @@ public static string ComputeSmartName(string typeName, string className)
1212
nameWords.Except(classNameWords));
1313
}
1414

15+
public static string ComputeSmartNameForCombinedEnums(string[] names)
16+
{
17+
var words = names
18+
.SelectMany(SplitToWordsByUpperCharacters)
19+
.GroupBy(x => x)
20+
.Where(x => x.Count() == names.Length)
21+
.Select(x => x.Key)
22+
.ToArray();
23+
24+
// Combine the repeated words from all names
25+
return string.Concat(words);
26+
}
27+
1528
public static IReadOnlyList<string> SplitToWordsByUpperCharacters(string text)
1629
{
1730
text = text ?? throw new ArgumentNullException(nameof(text));

0 commit comments

Comments
 (0)