Skip to content
This repository was archived by the owner on Nov 11, 2025. It is now read-only.

Commit 7f869d0

Browse files
committed
feat: adds the new 3.2 serialization infrastructure
Signed-off-by: Vincent Biret <[email protected]>
1 parent c8d87d7 commit 7f869d0

34 files changed

+324
-23
lines changed

src/Microsoft.OpenApi/Interfaces/IOpenApiSerializable.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ namespace Microsoft.OpenApi
88
/// </summary>
99
public interface IOpenApiSerializable : IOpenApiElement
1010
{
11+
/// <summary>
12+
/// Serialize OpenAPI element into v3.2
13+
/// </summary>
14+
/// <param name="writer"></param>
15+
void SerializeAsV32(IOpenApiWriter writer);
1116
/// <summary>
1217
/// Serialize OpenAPI element into v3.1
1318
/// </summary>

src/Microsoft.OpenApi/Models/BaseOpenApiReference.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,12 +150,27 @@ public BaseOpenApiReference(BaseOpenApiReference reference)
150150
HostDocument = reference.HostDocument;
151151
}
152152

153+
/// <inheritdoc/>
154+
public virtual void SerializeAsV32(IOpenApiWriter writer)
155+
{
156+
SerializeInternal(writer, SerializeAdditionalV32Properties);
157+
}
158+
153159
/// <inheritdoc/>
154160
public virtual void SerializeAsV31(IOpenApiWriter writer)
155161
{
156162
SerializeInternal(writer, SerializeAdditionalV31Properties);
157163
}
158164

165+
/// <summary>
166+
/// Serialize additional properties for Open Api v3.2.
167+
/// </summary>
168+
/// <param name="writer"></param>
169+
protected virtual void SerializeAdditionalV32Properties(IOpenApiWriter writer)
170+
{
171+
// noop for the base type
172+
}
173+
159174
/// <summary>
160175
/// Serialize additional properties for Open Api v3.1.
161176
/// </summary>

src/Microsoft.OpenApi/Models/JsonSchemaReference.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,11 +71,20 @@ public JsonSchemaReference(JsonSchemaReference reference) : base(reference)
7171

7272
/// <inheritdoc/>
7373
protected override void SerializeAdditionalV31Properties(IOpenApiWriter writer)
74+
{
75+
SerializeAdditionalV3XProperties(writer, base.SerializeAdditionalV31Properties);
76+
}
77+
/// <inheritdoc/>
78+
protected override void SerializeAdditionalV32Properties(IOpenApiWriter writer)
79+
{
80+
SerializeAdditionalV3XProperties(writer, base.SerializeAdditionalV32Properties);
81+
}
82+
private void SerializeAdditionalV3XProperties(IOpenApiWriter writer, Action<IOpenApiWriter> baseSerializer)
7483
{
7584
if (Type != ReferenceType.Schema) throw new InvalidOperationException(
7685
$"JsonSchemaReference can only be serialized for ReferenceType.Schema, but was {Type}.");
7786

78-
base.SerializeAdditionalV31Properties(writer);
87+
baseSerializer(writer);
7988
// Additional schema metadata annotations in 3.1
8089
writer.WriteOptionalObject(OpenApiConstants.Default, Default, (w, d) => w.WriteAny(d));
8190
writer.WriteProperty(OpenApiConstants.Title, Title);

src/Microsoft.OpenApi/Models/OpenApiCallback.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,16 @@ public void AddPathItem(RuntimeExpression expression, IOpenApiPathItem pathItem)
5050
PathItems.Add(expression, pathItem);
5151
}
5252

53+
/// <summary>
54+
/// Serialize <see cref="OpenApiCallback"/> to Open Api v3.2
55+
/// </summary>
56+
/// <param name="writer"></param>
57+
/// <exception cref="System.NotImplementedException"></exception>
58+
public virtual void SerializeAsV32(IOpenApiWriter writer)
59+
{
60+
SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_2, (writer, element) => element.SerializeAsV32(writer));
61+
}
62+
5363
/// <summary>
5464
/// Serialize <see cref="OpenApiCallback"/> to Open Api v3.1
5565
/// </summary>

src/Microsoft.OpenApi/Models/OpenApiComponents.cs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -90,19 +90,32 @@ public OpenApiComponents(OpenApiComponents? components)
9090
Extensions = components?.Extensions != null ? new Dictionary<string, IOpenApiExtension>(components.Extensions) : null;
9191
}
9292

93+
/// <summary>
94+
/// Serialize <see cref="OpenApiComponents"/> to Open API v3.2.
95+
/// </summary>
96+
/// <param name="writer"></param>
97+
public virtual void SerializeAsV32(IOpenApiWriter writer)
98+
{
99+
SerializeAsV3X(writer, OpenApiSpecVersion.OpenApi3_2, (writer, element) => element.SerializeAsV32(writer), (writer, referenceElement) => referenceElement.SerializeAsV32(writer));
100+
}
101+
93102
/// <summary>
94103
/// Serialize <see cref="OpenApiComponents"/> to Open API v3.1.
95104
/// </summary>
96105
/// <param name="writer"></param>
97106
public virtual void SerializeAsV31(IOpenApiWriter writer)
107+
{
108+
SerializeAsV3X(writer, OpenApiSpecVersion.OpenApi3_1, (writer, element) => element.SerializeAsV31(writer), (writer, referenceElement) => referenceElement.SerializeAsV31(writer));
109+
}
110+
private void SerializeAsV3X(IOpenApiWriter writer, OpenApiSpecVersion version, Action<IOpenApiWriter, IOpenApiSerializable> callback, Action<IOpenApiWriter, IOpenApiReferenceHolder> action)
98111
{
99112
Utils.CheckArgumentNull(writer);
100113

101114
// If references have been inlined we don't need the to render the components section
102115
// however if they have cycles, then we will need a component rendered
103116
if (writer.GetSettings().InlineLocalReferences)
104117
{
105-
RenderComponents(writer, (writer, element) => element.SerializeAsV31(writer), OpenApiSpecVersion.OpenApi3_1);
118+
RenderComponents(writer, callback, version);
106119
return;
107120
}
108121

@@ -116,16 +129,15 @@ public virtual void SerializeAsV31(IOpenApiWriter writer)
116129
{
117130
if (component is OpenApiPathItemReference reference)
118131
{
119-
reference.SerializeAsV31(w);
132+
action(w, reference);
120133
}
121134
else
122135
{
123-
component.SerializeAsV31(w);
136+
callback(w, component);
124137
}
125138
});
126139

127-
SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_1, (writer, element) => element.SerializeAsV31(writer),
128-
(writer, referenceElement) => referenceElement.SerializeAsV31(writer));
140+
SerializeInternal(writer, version, callback, action);
129141
}
130142

131143
/// <summary>

src/Microsoft.OpenApi/Models/OpenApiContact.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,14 @@ public OpenApiContact(OpenApiContact contact)
4747
Email = contact?.Email ?? Email;
4848
Extensions = contact?.Extensions != null ? new Dictionary<string, IOpenApiExtension>(contact.Extensions) : null;
4949
}
50+
/// <summary>
51+
/// Serialize <see cref="OpenApiContact"/> to Open Api v3.2
52+
/// </summary>
53+
/// <param name="writer"></param>
54+
public virtual void SerializeAsV32(IOpenApiWriter writer)
55+
{
56+
WriteInternal(writer, OpenApiSpecVersion.OpenApi3_2);
57+
}
5058

5159
/// <summary>
5260
/// Serialize <see cref="OpenApiContact"/> to Open Api v3.1

src/Microsoft.OpenApi/Models/OpenApiDiscriminator.cs

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,27 @@ public OpenApiDiscriminator(OpenApiDiscriminator discriminator)
4040
Extensions = discriminator?.Extensions != null ? new Dictionary<string, IOpenApiExtension>(discriminator.Extensions) : null;
4141
}
4242

43+
/// <summary>
44+
/// Serialize <see cref="OpenApiDiscriminator"/> to Open Api v3.2
45+
/// </summary>
46+
/// <param name="writer"></param>
47+
public void SerializeAsV32(IOpenApiWriter writer)
48+
{
49+
SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_2);
50+
51+
// extensions
52+
writer.WriteExtensions(Extensions, OpenApiSpecVersion.OpenApi3_2);
53+
54+
writer.WriteEndObject();
55+
}
56+
4357
/// <summary>
4458
/// Serialize <see cref="OpenApiDiscriminator"/> to Open Api v3.1
4559
/// </summary>
4660
/// <param name="writer"></param>
4761
public void SerializeAsV31(IOpenApiWriter writer)
4862
{
49-
SerializeInternal(writer);
63+
SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_1);
5064

5165
// extensions
5266
writer.WriteExtensions(Extensions, OpenApiSpecVersion.OpenApi3_1);
@@ -59,16 +73,12 @@ public void SerializeAsV31(IOpenApiWriter writer)
5973
/// </summary>
6074
public void SerializeAsV3(IOpenApiWriter writer)
6175
{
62-
SerializeInternal(writer);
76+
SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0);
6377

6478
writer.WriteEndObject();
6579
}
6680

67-
/// <summary>
68-
/// Serialize <see cref="OpenApiDiscriminator"/> to Open Api v3.0
69-
/// </summary>
70-
/// <param name="writer"></param>
71-
private void SerializeInternal(IOpenApiWriter writer)
81+
private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version)
7282
{
7383
Utils.CheckArgumentNull(writer);
7484

src/Microsoft.OpenApi/Models/OpenApiDocument.cs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -167,23 +167,36 @@ public void SerializeAs(OpenApiSpecVersion version, IOpenApiWriter writer)
167167
}
168168
}
169169

170+
/// <summary>
171+
/// Serialize <see cref="OpenApiDocument"/> to Open API v3.2 document.
172+
/// </summary>
173+
/// <param name="writer"></param>
174+
public void SerializeAsV32(IOpenApiWriter writer)
175+
{
176+
SerializeAsV3X(writer, "3.2.0", OpenApiSpecVersion.OpenApi3_2, (w, element) => element.SerializeAsV32(w), (w, referenceElement) => referenceElement.SerializeAsV32(w));
177+
}
178+
170179
/// <summary>
171180
/// Serialize <see cref="OpenApiDocument"/> to Open API v3.1 document.
172181
/// </summary>
173182
/// <param name="writer"></param>
174183
public void SerializeAsV31(IOpenApiWriter writer)
184+
{
185+
SerializeAsV3X(writer, "3.1.2", OpenApiSpecVersion.OpenApi3_1, (w, element) => element.SerializeAsV31(w), (w, referenceElement) => referenceElement.SerializeAsV31(w));
186+
}
187+
private void SerializeAsV3X(IOpenApiWriter writer, string versionString, OpenApiSpecVersion version, Action<IOpenApiWriter, IOpenApiSerializable> callback, Action<IOpenApiWriter, OpenApiPathItemReference> referenceCallback)
175188
{
176189
Utils.CheckArgumentNull(writer);
177190

178191
writer.WriteStartObject();
179192

180193
// openApi
181-
writer.WriteProperty(OpenApiConstants.OpenApi, "3.1.1");
194+
writer.WriteProperty(OpenApiConstants.OpenApi, versionString);
182195

183196
// jsonSchemaDialect
184197
writer.WriteProperty(OpenApiConstants.JsonSchemaDialect, JsonSchemaDialect?.ToString());
185198

186-
SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_1, (w, element) => element.SerializeAsV31(w));
199+
SerializeInternal(writer, version, callback);
187200

188201
// webhooks
189202
writer.WriteOptionalMap(
@@ -193,11 +206,11 @@ public void SerializeAsV31(IOpenApiWriter writer)
193206
{
194207
if (component is OpenApiPathItemReference reference)
195208
{
196-
reference.SerializeAsV31(w);
209+
referenceCallback(w, reference);
197210
}
198211
else
199212
{
200-
component.SerializeAsV31(w);
213+
callback(w, component);
201214
}
202215
});
203216

src/Microsoft.OpenApi/Models/OpenApiEncoding.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,15 @@ public OpenApiEncoding(OpenApiEncoding encoding)
7676
Extensions = encoding?.Extensions != null ? new Dictionary<string, IOpenApiExtension>(encoding.Extensions) : null;
7777
}
7878

79+
/// <summary>
80+
/// Serialize <see cref="OpenApiEncoding"/> to Open Api v3.2
81+
/// </summary>
82+
/// <param name="writer"></param>
83+
public virtual void SerializeAsV32(IOpenApiWriter writer)
84+
{
85+
SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_2, (writer, element) => element.SerializeAsV32(writer));
86+
}
87+
7988
/// <summary>
8089
/// Serialize <see cref="OpenApiEncoding"/> to Open Api v3.1
8190
/// </summary>

src/Microsoft.OpenApi/Models/OpenApiExample.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,12 @@ internal OpenApiExample(IOpenApiExample example)
4545
Extensions = example.Extensions != null ? new Dictionary<string, IOpenApiExtension>(example.Extensions) : null;
4646
}
4747

48+
/// <inheritdoc/>
49+
public virtual void SerializeAsV32(IOpenApiWriter writer)
50+
{
51+
SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_2);
52+
}
53+
4854
/// <inheritdoc/>
4955
public virtual void SerializeAsV31(IOpenApiWriter writer)
5056
{

0 commit comments

Comments
 (0)