Skip to content

Commit aebb9db

Browse files
Copilotbaywet
andcommitted
Add encoding Dictionary field to OpenApiEncoding class for OpenAPI 3.2 support
Co-authored-by: baywet <[email protected]>
1 parent 54ebe44 commit aebb9db

File tree

6 files changed

+146
-0
lines changed

6 files changed

+146
-0
lines changed

src/Microsoft.OpenApi/Models/OpenApiEncoding.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System;
55
using System.Collections.Generic;
6+
using System.Linq;
67

78
namespace Microsoft.OpenApi
89
{
@@ -27,6 +28,12 @@ public class OpenApiEncoding : IOpenApiSerializable, IOpenApiExtensible
2728
/// </summary>
2829
public IDictionary<string, IOpenApiHeader>? Headers { get; set; }
2930

31+
/// <summary>
32+
/// A map of property names to their encoding information.
33+
/// The key is the property name and the value is the encoding object.
34+
/// </summary>
35+
public IDictionary<string, OpenApiEncoding>? Encoding { get; set; }
36+
3037
/// <summary>
3138
/// Describes how a specific property value will be serialized depending on its type.
3239
/// </summary>
@@ -70,6 +77,7 @@ public OpenApiEncoding(OpenApiEncoding encoding)
7077
{
7178
ContentType = encoding?.ContentType ?? ContentType;
7279
Headers = encoding?.Headers != null ? new Dictionary<string, IOpenApiHeader>(encoding.Headers) : null;
80+
Encoding = encoding?.Encoding != null ? new Dictionary<string, OpenApiEncoding>(encoding.Encoding.ToDictionary(kvp => kvp.Key, kvp => new OpenApiEncoding(kvp.Value))) : null;
7381
Style = encoding?.Style ?? Style;
7482
Explode = encoding?._explode;
7583
AllowReserved = encoding?.AllowReserved ?? AllowReserved;
@@ -119,6 +127,9 @@ private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version
119127
// headers
120128
writer.WriteOptionalMap(OpenApiConstants.Headers, Headers, callback);
121129

130+
// encoding
131+
writer.WriteOptionalMap(OpenApiConstants.Encoding, Encoding, callback);
132+
122133
// style
123134
writer.WriteProperty(OpenApiConstants.Style, Style?.GetDisplayName());
124135

src/Microsoft.OpenApi/Reader/V32/OpenApiEncodingDeserializer.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ internal static partial class OpenApiV32Deserializer
2222
o.Headers = n.CreateMap(LoadHeader, t);
2323
}
2424
},
25+
{
26+
"encoding", (o, n, t) =>
27+
{
28+
o.Encoding = n.CreateMap(LoadEncoding, t);
29+
}
30+
},
2531
{
2632
"style", (o, n, _) =>
2733
{

test/Microsoft.OpenApi.Readers.Tests/V32Tests/OpenApiEncodingTests.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.IO;
55
using System.Threading.Tasks;
66
using Microsoft.OpenApi.Reader;
7+
using System.Collections.Generic;
78
using Xunit;
89

910
namespace Microsoft.OpenApi.Readers.Tests.V32Tests
@@ -29,5 +30,26 @@ public async Task ParseEncodingWithAllowReservedShouldSucceed()
2930
AllowReserved = true
3031
}, encoding);
3132
}
33+
34+
[Fact]
35+
public async Task ParseEncodingWithNestedEncodingShouldSucceed()
36+
{
37+
// Act
38+
var encoding = await OpenApiModelFactory.LoadAsync<OpenApiEncoding>(Path.Combine(SampleFolderPath, "encodingWithNestedEncoding.yaml"), OpenApiSpecVersion.OpenApi3_2, new(), SettingsFixture.ReaderSettings);
39+
40+
// Assert
41+
Assert.NotNull(encoding);
42+
Assert.Equal("application/json", encoding.ContentType);
43+
Assert.NotNull(encoding.Headers);
44+
Assert.Single(encoding.Headers);
45+
Assert.NotNull(encoding.Encoding);
46+
Assert.Equal(2, encoding.Encoding.Count);
47+
Assert.True(encoding.Encoding.ContainsKey("nestedField"));
48+
Assert.Equal("application/xml", encoding.Encoding["nestedField"].ContentType);
49+
Assert.Equal(ParameterStyle.Form, encoding.Encoding["nestedField"].Style);
50+
Assert.True(encoding.Encoding["nestedField"].Explode);
51+
Assert.True(encoding.Encoding.ContainsKey("anotherField"));
52+
Assert.Equal("text/plain", encoding.Encoding["anotherField"].ContentType);
53+
}
3254
}
3355
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.2.0.md#encodingObject
2+
contentType: application/json
3+
headers:
4+
X-Rate-Limit-Limit:
5+
description: The number of allowed requests in the current period
6+
schema:
7+
type: integer
8+
encoding:
9+
nestedField:
10+
contentType: application/xml
11+
style: form
12+
explode: true
13+
anotherField:
14+
contentType: text/plain

test/Microsoft.OpenApi.Tests/Models/OpenApiEncodingTests.cs

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT license.
33

4+
using System.Collections.Generic;
45
using System.Threading.Tasks;
56
using Xunit;
67

@@ -126,5 +127,96 @@ public async Task WhenExplodeIsSetOutputShouldHaveExplode(bool? expectedExplode,
126127
expected = expected.MakeLineBreaksEnvironmentNeutral();
127128
Assert.Equal(actual, expected);
128129
}
130+
131+
[Fact]
132+
public async Task SerializeEncodingWithNestedEncodingAsV32JsonWorks()
133+
{
134+
// Arrange
135+
var encoding = new OpenApiEncoding
136+
{
137+
ContentType = "application/json",
138+
Encoding = new Dictionary<string, OpenApiEncoding>
139+
{
140+
["nestedField"] = new OpenApiEncoding
141+
{
142+
ContentType = "application/xml",
143+
Style = ParameterStyle.Form,
144+
Explode = true
145+
},
146+
["anotherField"] = new OpenApiEncoding
147+
{
148+
ContentType = "text/plain"
149+
}
150+
}
151+
};
152+
153+
var expected =
154+
"""
155+
{
156+
"contentType": "application/json",
157+
"encoding": {
158+
"nestedField": {
159+
"contentType": "application/xml",
160+
"style": "form",
161+
"explode": true
162+
},
163+
"anotherField": {
164+
"contentType": "text/plain"
165+
}
166+
}
167+
}
168+
""";
169+
170+
// Act
171+
var actual = await encoding.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_2);
172+
173+
// Assert
174+
actual = actual.MakeLineBreaksEnvironmentNeutral();
175+
expected = expected.MakeLineBreaksEnvironmentNeutral();
176+
Assert.Equal(expected, actual);
177+
}
178+
179+
[Fact]
180+
public async Task SerializeEncodingWithNestedEncodingAsV32YamlWorks()
181+
{
182+
// Arrange
183+
var encoding = new OpenApiEncoding
184+
{
185+
ContentType = "application/json",
186+
Encoding = new Dictionary<string, OpenApiEncoding>
187+
{
188+
["nestedField"] = new OpenApiEncoding
189+
{
190+
ContentType = "application/xml",
191+
Style = ParameterStyle.Form,
192+
Explode = true
193+
},
194+
["anotherField"] = new OpenApiEncoding
195+
{
196+
ContentType = "text/plain"
197+
}
198+
}
199+
};
200+
201+
var expected =
202+
"""
203+
contentType: application/json
204+
encoding:
205+
nestedField:
206+
contentType: application/xml
207+
style: form
208+
explode: true
209+
anotherField:
210+
contentType: text/plain
211+
""";
212+
213+
// Act
214+
var actual = await encoding.SerializeAsYamlAsync(OpenApiSpecVersion.OpenApi3_2);
215+
216+
// Assert
217+
actual = actual.MakeLineBreaksEnvironmentNeutral();
218+
expected = expected.MakeLineBreaksEnvironmentNeutral();
219+
Assert.Equal(expected, actual);
220+
}
129221
}
130222
}

test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -679,6 +679,7 @@ namespace Microsoft.OpenApi
679679
public OpenApiEncoding(Microsoft.OpenApi.OpenApiEncoding encoding) { }
680680
public bool? AllowReserved { get; set; }
681681
public string? ContentType { get; set; }
682+
public System.Collections.Generic.IDictionary<string, Microsoft.OpenApi.OpenApiEncoding>? Encoding { get; set; }
682683
public bool? Explode { get; set; }
683684
public System.Collections.Generic.IDictionary<string, Microsoft.OpenApi.IOpenApiExtension>? Extensions { get; set; }
684685
public System.Collections.Generic.IDictionary<string, Microsoft.OpenApi.IOpenApiHeader>? Headers { get; set; }

0 commit comments

Comments
 (0)