Skip to content

Commit 2987561

Browse files
committed
feat(models): add shared Content interface
1 parent 4ee34a8 commit 2987561

File tree

9 files changed

+71
-53
lines changed

9 files changed

+71
-53
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using System.Collections.Generic;
2+
3+
namespace Microsoft.OpenApi;
4+
5+
/// <summary>
6+
/// Describes an element that has content.
7+
/// </summary>
8+
public interface IOpenApiContentElement
9+
{
10+
/// <summary>
11+
/// A map containing descriptions of potential payloads.
12+
/// The key is a media type or media type range and the value describes it.
13+
/// </summary>
14+
IDictionary<string, IOpenApiMediaType>? Content { get; set; }
15+
}
16+
17+
/// <summary>
18+
/// Describes an element that has content.
19+
/// </summary>
20+
public interface IOpenApiReadOnlyContentElement
21+
{
22+
/// <summary>
23+
/// A map containing descriptions of potential payloads.
24+
/// The key is a media type or media type range and the value describes it.
25+
/// </summary>
26+
IDictionary<string, IOpenApiMediaType>? Content { get; }
27+
}

src/Microsoft.OpenApi/Models/Interfaces/IOpenApiHeader.cs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace Microsoft.OpenApi;
88
/// Defines the base properties for the headers object.
99
/// This interface is provided for type assertions but should not be implemented by package consumers beyond automatic mocking.
1010
/// </summary>
11-
public interface IOpenApiHeader : IOpenApiDescribedElement, IOpenApiReadOnlyExtensible, IShallowCopyable<IOpenApiHeader>, IOpenApiReferenceable
11+
public interface IOpenApiHeader : IOpenApiDescribedElement, IOpenApiReadOnlyExtensible, IShallowCopyable<IOpenApiHeader>, IOpenApiReferenceable, IOpenApiReadOnlyContentElement
1212
{
1313
/// <summary>
1414
/// Determines whether this header is mandatory.
@@ -58,9 +58,4 @@ public interface IOpenApiHeader : IOpenApiDescribedElement, IOpenApiReadOnlyExte
5858
/// </summary>
5959
public IDictionary<string, IOpenApiExample>? Examples { get; }
6060

61-
/// <summary>
62-
/// A map containing the representations for the header.
63-
/// </summary>
64-
public IDictionary<string, IOpenApiMediaType>? Content { get; }
65-
6661
}

src/Microsoft.OpenApi/Models/Interfaces/IOpenApiParameter.cs

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ namespace Microsoft.OpenApi;
77
/// Defines the base properties for the parameter object.
88
/// This interface is provided for type assertions but should not be implemented by package consumers beyond automatic mocking.
99
/// </summary>
10-
public interface IOpenApiParameter : IOpenApiDescribedElement, IOpenApiReadOnlyExtensible, IShallowCopyable<IOpenApiParameter>, IOpenApiReferenceable
10+
public interface IOpenApiParameter : IOpenApiDescribedElement, IOpenApiReadOnlyExtensible, IShallowCopyable<IOpenApiParameter>, IOpenApiReferenceable, IOpenApiReadOnlyContentElement
1111
{
1212
/// <summary>
1313
/// REQUIRED. The name of the parameter. Parameter names are case sensitive.
@@ -93,15 +93,4 @@ public interface IOpenApiParameter : IOpenApiDescribedElement, IOpenApiReadOnlyE
9393
/// Assign <see cref="JsonNullSentinel.JsonNull"/> to use get null as a serialized value.
9494
/// </summary>
9595
public JsonNode? Example { get; }
96-
97-
/// <summary>
98-
/// A map containing the representations for the parameter.
99-
/// The key is the media type and the value describes it.
100-
/// The map MUST only contain one entry.
101-
/// For more complex scenarios, the content property can define the media type and schema of the parameter.
102-
/// A parameter MUST contain either a schema property, or a content property, but not both.
103-
/// When example or examples are provided in conjunction with the schema object,
104-
/// the example MUST follow the prescribed serialization strategy for the parameter.
105-
/// </summary>
106-
public IDictionary<string, IOpenApiMediaType>? Content { get; }
10796
}

src/Microsoft.OpenApi/Models/Interfaces/IOpenApiRequestBody.cs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,13 @@ namespace Microsoft.OpenApi;
66
/// Defines the base properties for the request body object.
77
/// This interface is provided for type assertions but should not be implemented by package consumers beyond automatic mocking.
88
/// </summary>
9-
public interface IOpenApiRequestBody : IOpenApiDescribedElement, IOpenApiReadOnlyExtensible, IShallowCopyable<IOpenApiRequestBody>, IOpenApiReferenceable
9+
public interface IOpenApiRequestBody : IOpenApiDescribedElement, IOpenApiReadOnlyExtensible, IShallowCopyable<IOpenApiRequestBody>, IOpenApiReferenceable, IOpenApiReadOnlyContentElement
1010
{
1111
/// <summary>
1212
/// Determines if the request body is required in the request. Defaults to false.
1313
/// </summary>
1414
public bool Required { get; }
1515

16-
/// <summary>
17-
/// REQUIRED. The content of the request body. The key is a media type or media type range and the value describes it.
18-
/// For requests that match multiple keys, only the most specific key is applicable. e.g. text/plain overrides text/*
19-
/// </summary>
20-
public IDictionary<string, IOpenApiMediaType>? Content { get; }
2116
/// <summary>
2217
/// Converts the request body to a body parameter in preparation for a v2 serialization.
2318
/// </summary>

src/Microsoft.OpenApi/Models/Interfaces/IOpenApiResponse.cs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,13 @@ namespace Microsoft.OpenApi;
66
/// Defines the base properties for the response object.
77
/// This interface is provided for type assertions but should not be implemented by package consumers beyond automatic mocking.
88
/// </summary>
9-
public interface IOpenApiResponse : IOpenApiDescribedElement, IOpenApiReadOnlyExtensible, IShallowCopyable<IOpenApiResponse>, IOpenApiReferenceable, IOpenApiSummarizedElement
9+
public interface IOpenApiResponse : IOpenApiDescribedElement, IOpenApiReadOnlyExtensible, IShallowCopyable<IOpenApiResponse>, IOpenApiReferenceable, IOpenApiSummarizedElement, IOpenApiReadOnlyContentElement
1010
{
1111
/// <summary>
1212
/// Maps a header name to its definition.
1313
/// </summary>
1414
public IDictionary<string, IOpenApiHeader>? Headers { get; }
1515

16-
/// <summary>
17-
/// A map containing descriptions of potential response payloads.
18-
/// The key is a media type or media type range and the value describes it.
19-
/// </summary>
20-
public IDictionary<string, IOpenApiMediaType>? Content { get; }
21-
2216
/// <summary>
2317
/// A map of operations links that can be followed from the response.
2418
/// The key of the map is a short name for the link,

src/Microsoft.OpenApi/Models/OpenApiHeader.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ namespace Microsoft.OpenApi
1111
/// Header Object.
1212
/// The Header Object follows the structure of the Parameter Object.
1313
/// </summary>
14-
public class OpenApiHeader : IOpenApiHeader, IOpenApiExtensible
14+
public class OpenApiHeader : IOpenApiHeader, IOpenApiExtensible, IOpenApiContentElement
1515
{
1616
/// <inheritdoc/>
1717
public string? Description { get; set; }
@@ -43,7 +43,9 @@ public class OpenApiHeader : IOpenApiHeader, IOpenApiExtensible
4343
/// <inheritdoc/>
4444
public IDictionary<string, IOpenApiExample>? Examples { get; set; }
4545

46-
/// <inheritdoc/>
46+
/// <summary>
47+
/// A map containing the representations for the header.
48+
/// </summary>
4749
public IDictionary<string, IOpenApiMediaType>? Content { get; set; }
4850

4951
/// <inheritdoc/>
@@ -98,7 +100,7 @@ public virtual void SerializeAsV3(IOpenApiWriter writer)
98100
SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0, (writer, element) => element.SerializeAsV3(writer));
99101
}
100102

101-
internal void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version,
103+
internal void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version,
102104
Action<IOpenApiWriter, IOpenApiSerializable> callback)
103105
{
104106
Utils.CheckArgumentNull(writer);
@@ -175,7 +177,8 @@ public virtual void SerializeAsV2(IOpenApiWriter writer)
175177
writer.WriteProperty(OpenApiConstants.AllowReserved, AllowReserved, false);
176178

177179
// schema
178-
var targetSchema = Schema switch {
180+
var targetSchema = Schema switch
181+
{
179182
OpenApiSchemaReference schemaReference => schemaReference.RecursiveTarget,
180183
OpenApiSchema schema => schema,
181184
_ => null,

src/Microsoft.OpenApi/Models/OpenApiParameter.cs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ namespace Microsoft.OpenApi
1111
/// <summary>
1212
/// Parameter Object.
1313
/// </summary>
14-
public class OpenApiParameter : IOpenApiExtensible, IOpenApiParameter
14+
public class OpenApiParameter : IOpenApiExtensible, IOpenApiParameter, IOpenApiContentElement
1515
{
1616
private bool? _explode;
1717
private ParameterStyle? _style;
@@ -60,7 +60,15 @@ public bool Explode
6060
/// <inheritdoc/>
6161
public JsonNode? Example { get; set; }
6262

63-
/// <inheritdoc/>
63+
/// <summary>
64+
/// A map containing the representations for the parameter.
65+
/// The key is the media type and the value describes it.
66+
/// The map MUST only contain one entry.
67+
/// For more complex scenarios, the content property can define the media type and schema of the parameter.
68+
/// A parameter MUST contain either a schema property, or a content property, but not both.
69+
/// When example or examples are provided in conjunction with the schema object,
70+
/// the example MUST follow the prescribed serialization strategy for the parameter.
71+
/// </summary>
6472
public IDictionary<string, IOpenApiMediaType>? Content { get; set; }
6573

6674
/// <inheritdoc/>
@@ -111,11 +119,11 @@ public virtual void SerializeAsV3(IOpenApiWriter writer)
111119
SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0, (writer, element) => element.SerializeAsV3(writer));
112120
}
113121

114-
internal void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version,
122+
internal void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version,
115123
Action<IOpenApiWriter, IOpenApiSerializable> callback)
116124
{
117125
Utils.CheckArgumentNull(writer);
118-
126+
119127
// Validate that Cookie style is only used in OpenAPI 3.2 and later
120128
if (Style == ParameterStyle.Cookie && version < OpenApiSpecVersion.OpenApi3_2)
121129
{
@@ -226,7 +234,8 @@ internal virtual void WriteRequestBodySchemaForV2(IOpenApiWriter writer, Diction
226234
// uniqueItems
227235
// enum
228236
// multipleOf
229-
var targetSchema = Schema switch {
237+
var targetSchema = Schema switch
238+
{
230239
OpenApiSchemaReference schemaReference => schemaReference.RecursiveTarget,
231240
OpenApiSchema schema => schema,
232241
_ => null,
@@ -271,7 +280,7 @@ internal virtual void WriteRequestBodySchemaForV2(IOpenApiWriter writer, Diction
271280
public virtual void SerializeAsV2(IOpenApiWriter writer)
272281
{
273282
Utils.CheckArgumentNull(writer);
274-
283+
275284
// Validate that Cookie style is only used in OpenAPI 3.2 and later
276285
if (Style == ParameterStyle.Cookie)
277286
{

src/Microsoft.OpenApi/Models/OpenApiRequestBody.cs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,18 @@ namespace Microsoft.OpenApi
1010
/// <summary>
1111
/// Request Body Object
1212
/// </summary>
13-
public class OpenApiRequestBody : IOpenApiExtensible, IOpenApiRequestBody
13+
public class OpenApiRequestBody : IOpenApiExtensible, IOpenApiRequestBody, IOpenApiContentElement
1414
{
1515
/// <inheritdoc />
1616
public string? Description { get; set; }
1717

1818
/// <inheritdoc />
1919
public bool Required { get; set; }
2020

21-
/// <inheritdoc />
21+
/// <summary>
22+
/// REQUIRED. The content of the request body. The key is a media type or media type range and the value describes it.
23+
/// For requests that match multiple keys, only the most specific key is applicable. e.g. text/plain overrides text/*
24+
/// </summary>
2225
public IDictionary<string, IOpenApiMediaType>? Content { get; set; }
2326

2427
/// <inheritdoc />
@@ -64,7 +67,7 @@ public virtual void SerializeAsV3(IOpenApiWriter writer)
6467
{
6568
SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0, (writer, element) => element.SerializeAsV3(writer));
6669
}
67-
70+
6871
internal void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version,
6972
Action<IOpenApiWriter, IOpenApiSerializable> callback)
7073
{
@@ -110,7 +113,7 @@ public IOpenApiParameter ConvertToBodyParameter(IOpenApiWriter writer)
110113
Extensions = Extensions?.ToDictionary(static k => k.Key, static v => v.Value)
111114
};
112115
// Clone extensions so we can remove the x-bodyName extensions from the output V2 model.
113-
if (bodyParameter.Extensions is not null &&
116+
if (bodyParameter.Extensions is not null &&
114117
bodyParameter.Extensions.TryGetValue(OpenApiConstants.BodyName, out var bodyNameExtension) &&
115118
bodyNameExtension is JsonNodeExtension bodyName)
116119
{
@@ -126,7 +129,7 @@ public IEnumerable<IOpenApiParameter> ConvertToFormDataParameters(IOpenApiWriter
126129
if (Content == null || !Content.Any())
127130
yield break;
128131
var properties = Content.First().Value.Schema?.Properties;
129-
if(properties != null)
132+
if (properties != null)
130133
{
131134
foreach (var property in properties)
132135
{
@@ -144,11 +147,11 @@ public IEnumerable<IOpenApiParameter> ConvertToFormDataParameters(IOpenApiWriter
144147
OpenApiSchemaReference => throw new InvalidOperationException("Unresolved reference target"),
145148
_ => throw new InvalidOperationException("Unexpected schema type")
146149
};
147-
150+
148151
updatedSchema.Type = "file".ToJsonSchemaType();
149152
updatedSchema.Format = null;
150153
paramSchema = updatedSchema;
151-
154+
152155
}
153156
yield return new OpenApiFormDataParameter()
154157
{
@@ -159,7 +162,7 @@ public IEnumerable<IOpenApiParameter> ConvertToFormDataParameters(IOpenApiWriter
159162
Required = Content.First().Value.Schema?.Required?.Contains(property.Key) ?? false
160163
};
161164
}
162-
}
165+
}
163166
}
164167

165168
/// <inheritdoc/>

src/Microsoft.OpenApi/Models/OpenApiResponse.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ namespace Microsoft.OpenApi
1010
/// <summary>
1111
/// Response object.
1212
/// </summary>
13-
public class OpenApiResponse : IOpenApiExtensible, IOpenApiResponse
13+
public class OpenApiResponse : IOpenApiExtensible, IOpenApiResponse, IOpenApiContentElement
1414
{
1515
/// <inheritdoc/>
1616
public string? Summary { get; set; }
@@ -21,7 +21,10 @@ public class OpenApiResponse : IOpenApiExtensible, IOpenApiResponse
2121
/// <inheritdoc/>
2222
public IDictionary<string, IOpenApiHeader>? Headers { get; set; }
2323

24-
/// <inheritdoc/>
24+
/// <summary>
25+
/// A map containing descriptions of potential response payloads.
26+
/// The key is a media type or media type range and the value describes it.
27+
/// </summary>
2528
public IDictionary<string, IOpenApiMediaType>? Content { get; set; }
2629

2730
/// <inheritdoc/>
@@ -73,7 +76,7 @@ public virtual void SerializeAsV3(IOpenApiWriter writer)
7376
SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0, (writer, element) => element.SerializeAsV3(writer));
7477
}
7578

76-
private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version,
79+
private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version,
7780
Action<IOpenApiWriter, IOpenApiSerializable> callback)
7881
{
7982
Utils.CheckArgumentNull(writer);
@@ -177,7 +180,7 @@ public virtual void SerializeAsV2(IOpenApiWriter writer)
177180
// so remove it from the cloned collection so we don't write it again.
178181
extensionsClone?.Remove(key);
179182
}
180-
}
183+
}
181184
}
182185
}
183186

0 commit comments

Comments
 (0)