@@ -12,10 +12,31 @@ extension OpenAPI {
1212 ///
1313 /// See [OpenAPI Media Type Object](https://spec.openapis.org/oas/v3.1.1.html#media-type-object).
1414 public struct Content : Equatable , CodableVendorExtendable , Sendable {
15+ /// A schema describing the complete content of the request, response,
16+ /// parameter, or header.
1517 public var schema : JSONSchema ?
18+
19+ /// A schema describing each item within a sequential media type.
20+ public var itemSchema : JSONSchema ?
21+
1622 public var example : AnyCodable ?
1723 public var examples : Example . Map ?
18- public var encoding : OrderedDictionary < String , Encoding > ?
24+
25+ /// Provide either a map of encodings or some combination of prefix-
26+ /// and item- positional encodings.
27+ ///
28+ /// If the OpenAPI Document specifies the 'encoding' key (a map)
29+ /// then this property will be set to its first case. If the OpenAPI
30+ /// Document specifies either or both of the 'prefixEncoding' and
31+ /// 'itemEncoding' keys, this property will be set to its second case.
32+ ///
33+ /// You can access the encoding map (OAS 'encoding' property) as the `Content`
34+ /// type's `encodingMap` as well.
35+ ///
36+ /// You can access the positional encoding (OAS 'prefixEncoding' and
37+ /// `itemEncoding` properties) as the `Content` type's `prefixEncoding`
38+ /// and `itemEncoding` properties.
39+ public var encoding : Either < OrderedDictionary < String , Encoding > , PositionalEncoding > ?
1940
2041 /// Dictionary of vendor extensions.
2142 ///
@@ -24,18 +45,87 @@ extension OpenAPI {
2445 /// where the values are anything codable.
2546 public var vendorExtensions : [ String : AnyCodable ]
2647
48+ /// The encoding of this `Content` (Media Type Object) if it is a map
49+ /// from property names to encoding information.
50+ ///
51+ /// This property gets modified as part of the `encoding` property.
52+ ///
53+ /// See also the `prefixEncoding` and `itemEncoding` properties.
54+ public var encodingMap : OrderedDictionary < String , Encoding > ? { encoding? . a }
55+
56+ /// The positional prefix-encoding for this `Content` (Media Type
57+ /// Object) if set.
58+ ///
59+ /// This property gets modified as part of the `encoding` property.
60+ ///
61+ /// See also the `itemEncoding` and `encodingMap` properties.
62+ public var prefixEncoding : [ Encoding ] ? { encoding? . b? . prefixEncoding }
63+
64+ /// The positional item-encoding for this `Content` (Media Type
65+ /// Object) if set.
66+ ///
67+ /// This property gets modified as part of the `encoding` property.
68+ ///
69+ /// See also the `prefixEncoding` and `encodingMap` properties.
70+ public var itemEncoding : Encoding ? { encoding? . b? . itemEncoding }
71+
2772 /// Create `Content` with a schema, a reference to a schema, or no
2873 /// schema at all and optionally provide a single example.
2974 public init (
3075 schema: JSONSchema ? ,
76+ itemSchema: JSONSchema ? = nil ,
3177 example: AnyCodable ? = nil ,
3278 encoding: OrderedDictionary < String , Encoding > ? = nil ,
3379 vendorExtensions: [ String : AnyCodable ] = [ : ]
3480 ) {
3581 self . schema = schema
82+ self . itemSchema = itemSchema
83+ self . example = example
84+ self . examples = nil
85+ self . encoding = encoding. map ( Either . a)
86+ self . vendorExtensions = vendorExtensions
87+ }
88+
89+ /// Create `Content` with a schema, a reference to a schema, or no
90+ /// schema at all and optionally provide a single example.
91+ public init (
92+ schema: JSONSchema ? ,
93+ itemSchema: JSONSchema ? = nil ,
94+ example: AnyCodable ? = nil ,
95+ prefixEncoding: [ Encoding ] = [ ] ,
96+ itemEncoding: Encoding ? = nil ,
97+ vendorExtensions: [ String : AnyCodable ] = [ : ]
98+ ) {
99+ self . schema = schema
100+ self . itemSchema = itemSchema
101+ self . example = example
102+ self . examples = nil
103+ if itemEncoding != nil || prefixEncoding != [ ] {
104+ self . encoding = . b( . init( prefixEncoding: prefixEncoding, itemEncoding: itemEncoding) )
105+ } else {
106+ self . encoding = nil
107+ }
108+ self . vendorExtensions = vendorExtensions
109+ }
110+
111+ /// Create `Content` with a schema, a reference to a schema, or no
112+ /// schema at all and optionally provide a single example.
113+ public init (
114+ itemSchema: JSONSchema ? ,
115+ example: AnyCodable ? = nil ,
116+ prefixEncoding: [ Encoding ] = [ ] ,
117+ itemEncoding: Encoding ? = nil ,
118+ vendorExtensions: [ String : AnyCodable ] = [ : ]
119+ ) {
120+ self . schema = nil
121+ self . itemSchema = itemSchema
36122 self . example = example
37123 self . examples = nil
38- self . encoding = encoding
124+ if itemEncoding != nil || prefixEncoding != [ ] {
125+ self . encoding = . b( . init( prefixEncoding: prefixEncoding, itemEncoding: itemEncoding) )
126+ } else {
127+ self . encoding = nil
128+ }
39129 self . vendorExtensions = vendorExtensions
40130 }
41131
@@ -50,22 +140,24 @@ extension OpenAPI {
50140 self . schema = . reference( schemaReference. jsonReference, description: schemaReference. description)
51141 self . example = example
52142 self . examples = nil
53- self . encoding = encoding
143+ self . encoding = encoding. map ( Either . a )
54144 self . vendorExtensions = vendorExtensions
55145 }
56146
57147 /// Create `Content` with a schema and optionally provide a single
58148 /// example.
59149 public init (
60150 schema: JSONSchema ,
151+ itemSchema: JSONSchema ? = nil ,
61152 example: AnyCodable ? = nil ,
62153 encoding: OrderedDictionary < String , Encoding > ? = nil ,
63154 vendorExtensions: [ String : AnyCodable ] = [ : ]
64155 ) {
65156 self . schema = schema
157+ self . itemSchema = itemSchema
66158 self . example = example
67159 self . examples = nil
68- self . encoding = encoding
160+ self . encoding = encoding. map ( Either . a )
69161 self . vendorExtensions = vendorExtensions
70162 }
71163
@@ -89,7 +181,7 @@ extension OpenAPI {
89181 }
90182 self . examples = examples
91183 self . example = examples. flatMap ( Self . firstExample ( from: ) )
92- self . encoding = encoding
184+ self . encoding = encoding. map ( Either . a )
93185 self . vendorExtensions = vendorExtensions
94186 }
95187
@@ -104,22 +196,61 @@ extension OpenAPI {
104196 self . schema = . reference( schemaReference. jsonReference)
105197 self . examples = examples
106198 self . example = examples. flatMap ( Self . firstExample ( from: ) )
107- self . encoding = encoding
199+ self . encoding = encoding. map ( Either . a )
108200 self . vendorExtensions = vendorExtensions
109201 }
110202
111203 /// Create `Content` with a schema and optionally provide a map
112204 /// of examples.
113205 public init (
114206 schema: JSONSchema ,
207+ itemSchema: JSONSchema ? = nil ,
115208 examples: Example . Map ? ,
116209 encoding: OrderedDictionary < String , Encoding > ? = nil ,
117210 vendorExtensions: [ String : AnyCodable ] = [ : ]
118211 ) {
119212 self . schema = schema
213+ self . itemSchema = itemSchema
214+ self . examples = examples
215+ self . example = examples. flatMap ( Self . firstExample ( from: ) )
216+ self . encoding = encoding. map ( Either . a)
217+ self . vendorExtensions = vendorExtensions
218+ }
219+
220+ /// Create `Content` with a schema and optionally provide a map
221+ /// of examples.
222+ public init (
223+ itemSchema: JSONSchema ? ,
224+ examples: Example . Map ? ,
225+ encoding: OrderedDictionary < String , Encoding > ? = nil ,
226+ vendorExtensions: [ String : AnyCodable ] = [ : ]
227+ ) {
228+ self . schema = nil
229+ self . itemSchema = itemSchema
230+ self . examples = examples
231+ self . example = examples. flatMap ( Self . firstExample ( from: ) )
232+ self . encoding = encoding. map ( Either . a)
233+ self . vendorExtensions = vendorExtensions
234+ }
235+
236+ /// Create `Content` with a schema and optionally provide a map
237+ /// of examples.
238+ public init (
239+ itemSchema: JSONSchema ? = nil ,
240+ examples: Example . Map ? ,
241+ prefixEncoding: [ Encoding ] = [ ] ,
242+ itemEncoding: Encoding ? = nil ,
243+ vendorExtensions: [ String : AnyCodable ] = [ : ]
244+ ) {
245+ self . schema = nil
246+ self . itemSchema = itemSchema
120247 self . examples = examples
121248 self . example = examples. flatMap ( Self . firstExample ( from: ) )
122- self . encoding = encoding
249+ if itemEncoding != nil || prefixEncoding != [ ] {
250+ self . encoding = . b( . init( prefixEncoding: prefixEncoding, itemEncoding: itemEncoding) )
251+ } else {
252+ self . encoding = nil
253+ }
123254 self . vendorExtensions = vendorExtensions
124255 }
125256 }
@@ -159,6 +290,7 @@ extension OpenAPI.Content: Encodable {
159290 var container = encoder. container ( keyedBy: CodingKeys . self)
160291
161292 try container. encodeIfPresent ( schema, forKey: . schema)
293+ try container. encodeIfPresent ( itemSchema, forKey: . itemSchema)
162294
163295 // only encode `examples` if non-nil,
164296 // otherwise encode `example` if non-nil
@@ -168,7 +300,18 @@ extension OpenAPI.Content: Encodable {
168300 try container. encode ( example, forKey: . example)
169301 }
170302
171- try container. encodeIfPresent ( encoding, forKey: . encoding)
303+ if let encoding {
304+ switch encoding {
305+ case . a( let encoding) :
306+ try container. encode ( encoding, forKey: . encoding)
307+
308+ case . b( let positionalEncoding) :
309+ if !positionalEncoding. prefixEncoding. isEmpty {
310+ try container. encode ( positionalEncoding. prefixEncoding, forKey: . prefixEncoding)
311+ }
312+ try container. encodeIfPresent ( positionalEncoding. itemEncoding, forKey: . itemEncoding)
313+ }
314+ }
172315
173316 if VendorExtensionsConfiguration . isEnabled ( for: encoder) {
174317 try encodeExtensions ( to: & container)
@@ -188,9 +331,27 @@ extension OpenAPI.Content: Decodable {
188331 )
189332 }
190333
334+ guard !( container. contains ( . encoding) && ( container. contains ( . prefixEncoding) || container. contains ( . itemEncoding) ) ) else {
335+ throw GenericError (
336+ subjectName: " Encoding and Positional Encoding " ,
337+ details: " If `prefixEncoding` or `itemEncoding` are specified then `encoding` is not allowed in the Media Type Object (`OpenAPI.Content`). " ,
338+ codingPath: container. codingPath
339+ )
340+ }
341+
191342 schema = try container. decodeIfPresent ( JSONSchema . self, forKey: . schema)
343+ itemSchema = try container. decodeIfPresent ( JSONSchema . self, forKey: . itemSchema)
344+
345+ if container. contains ( . encoding) {
346+ encoding = . a( try container. decode ( OrderedDictionary < String , Encoding > . self, forKey: . encoding) )
347+ } else if container. contains ( . prefixEncoding) || container. contains ( . itemEncoding) {
348+ let prefixEncoding = try container. decodeIfPresent ( [ Encoding ] . self, forKey: . prefixEncoding) ?? [ ]
349+ let itemEncoding = try container. decodeIfPresent ( Encoding . self, forKey: . itemEncoding)
192350
193- encoding = try container. decodeIfPresent ( OrderedDictionary < String , Encoding > . self, forKey: . encoding)
351+ encoding = . b( . init( prefixEncoding: prefixEncoding, itemEncoding: itemEncoding) )
352+ } else {
353+ encoding = nil
354+ }
194355
195356 if container. contains ( . example) {
196357 example = try container. decode ( AnyCodable . self, forKey: . example)
@@ -208,13 +369,24 @@ extension OpenAPI.Content: Decodable {
208369extension OpenAPI . Content {
209370 internal enum CodingKeys : ExtendableCodingKey {
210371 case schema
372+ case itemSchema
211373 case example // `example` and `examples` are mutually exclusive
212374 case examples // `example` and `examples` are mutually exclusive
213375 case encoding
376+ case itemEncoding
377+ case prefixEncoding
214378 case extended( String )
215379
216380 static var allBuiltinKeys : [ CodingKeys ] {
217- return [ . schema, . example, . examples, . encoding]
381+ return [
382+ . schema,
383+ . itemSchema,
384+ . example,
385+ . examples,
386+ . encoding,
387+ . itemEncoding,
388+ . prefixEncoding
389+ ]
218390 }
219391
220392 static func extendedKey( for value: String ) -> CodingKeys {
@@ -225,12 +397,18 @@ extension OpenAPI.Content {
225397 switch stringValue {
226398 case " schema " :
227399 self = . schema
400+ case " itemSchema " :
401+ self = . itemSchema
228402 case " example " :
229403 self = . example
230404 case " examples " :
231405 self = . examples
232406 case " encoding " :
233407 self = . encoding
408+ case " itemEncoding " :
409+ self = . itemEncoding
410+ case " prefixEncoding " :
411+ self = . prefixEncoding
234412 default :
235413 self = . extendedKey( for: stringValue)
236414 }
@@ -240,12 +418,18 @@ extension OpenAPI.Content {
240418 switch self {
241419 case . schema:
242420 return " schema "
421+ case . itemSchema:
422+ return " itemSchema "
243423 case . example:
244424 return " example "
245425 case . examples:
246426 return " examples "
247427 case . encoding:
248428 return " encoding "
429+ case . itemEncoding:
430+ return " itemEncoding "
431+ case . prefixEncoding:
432+ return " prefixEncoding "
249433 case . extended( let key) :
250434 return key
251435 }
0 commit comments