Skip to content

Commit a21615e

Browse files
authored
Merge pull request #409 from simonbility/feature/support-vendor-extensions-in-anyof-allof-oneof
Support vendor extensions in `anyOf` `allOf` `oneOf` for OAS 3.1
2 parents 4f31a7b + 4f947ba commit a21615e

File tree

2 files changed

+80
-16
lines changed

2 files changed

+80
-16
lines changed

Sources/OpenAPIKit/Schema Object/JSONSchema.swift

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1971,7 +1971,10 @@ extension JSONSchema: Decodable {
19711971
schema = schema.nullableSchemaObject()
19721972
}
19731973

1974-
self = schema
1974+
// Ad-hoc vendor extension support since JSONSchema does coding keys differently.
1975+
let extensions = try Self.decodeVenderExtensions(from: decoder)
1976+
1977+
self = schema.with(vendorExtensions: extensions)
19751978
return
19761979
}
19771980

@@ -1988,7 +1991,10 @@ extension JSONSchema: Decodable {
19881991
schema = schema.nullableSchemaObject()
19891992
}
19901993

1991-
self = schema
1994+
// Ad-hoc vendor extension support since JSONSchema does coding keys differently.
1995+
let extensions = try Self.decodeVenderExtensions(from: decoder)
1996+
1997+
self = schema.with(vendorExtensions: extensions)
19921998
return
19931999
}
19942000

@@ -2004,7 +2010,10 @@ extension JSONSchema: Decodable {
20042010
schema = schema.nullableSchemaObject()
20052011
}
20062012

2007-
self = schema
2013+
// Ad-hoc vendor extension support since JSONSchema does coding keys differently.
2014+
let extensions = try Self.decodeVenderExtensions(from: decoder)
2015+
2016+
self = schema.with(vendorExtensions: extensions)
20082017
return
20092018
}
20102019

@@ -2016,8 +2025,11 @@ extension JSONSchema: Decodable {
20162025
core: coreContext
20172026
)
20182027
)
2019-
2020-
self = schema
2028+
2029+
// Ad-hoc vendor extension support since JSONSchema does coding keys differently.
2030+
let extensions = try Self.decodeVenderExtensions(from: decoder)
2031+
2032+
self = schema.with(vendorExtensions: extensions)
20212033
return
20222034
}
20232035

@@ -2132,29 +2144,30 @@ extension JSONSchema: Decodable {
21322144

21332145
self.warnings = _warnings
21342146

2135-
// Ad-hoc vendor extension support since JSONSchema does coding keys differently.
2136-
let extensions: [String: AnyCodable]
2147+
// Ad-hoc vendor extension support since JSONSchema does coding keys differently.
2148+
let extensions = try Self.decodeVenderExtensions(from: decoder)
21372149

2150+
self.value = value.with(vendorExtensions: extensions)
2151+
}
2152+
2153+
private static func decodeVenderExtensions(from decoder: Decoder) throws -> [String: AnyCodable] {
21382154
guard VendorExtensionsConfiguration.isEnabled else {
2139-
self.value = value
2140-
return
2155+
return [:]
21412156
}
2142-
2157+
21432158
let decoded = try AnyCodable(from: decoder).value
2144-
2159+
21452160
guard (decoded as? [Any]) == nil else {
21462161
throw VendorExtensionDecodingError.selfIsArrayNotDict
21472162
}
2148-
2163+
21492164
guard let decodedAny = decoded as? [String: Any] else {
21502165
throw VendorExtensionDecodingError.foundNonStringKeys
21512166
}
2152-
2153-
extensions = decodedAny
2167+
2168+
return decodedAny
21542169
.filter { $0.key.lowercased().starts(with: "x-") }
21552170
.mapValues(AnyCodable.init)
2156-
2157-
self.value = value.with(vendorExtensions: extensions)
21582171
}
21592172

21602173
private static func decodeTypes(from container: KeyedDecodingContainer<JSONSchema.HintCodingKeys>) throws -> [JSONType] {

Tests/OpenAPIKitTests/Schema Object/JSONSchemaTests.swift

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1918,6 +1918,57 @@ extension SchemaObjectTests {
19181918
JSONSchema.fragment(.init(examples: ["hello"])).with(vendorExtensions: ["x-hello": "hello"])
19191919
)
19201920
}
1921+
1922+
func test_decodeAnyOfWithVendorExtension() throws {
1923+
let extensionSchema = """
1924+
{
1925+
"anyOf" : [
1926+
{ "type": "string" },
1927+
{ "type": "number" }
1928+
],
1929+
"x-hello" : "hello"
1930+
}
1931+
""".data(using: .utf8)!
1932+
1933+
XCTAssertEqual(
1934+
try orderUnstableDecode(JSONSchema.self, from: extensionSchema),
1935+
JSONSchema.any(of: [JSONSchema.string, JSONSchema.number]).with(vendorExtensions: ["x-hello": "hello"])
1936+
)
1937+
}
1938+
1939+
func test_decodeAllOfWithVendorExtension() throws {
1940+
let extensionSchema = """
1941+
{
1942+
"allOf" : [
1943+
{ "type": "string" },
1944+
{ "type": "number" }
1945+
],
1946+
"x-hello" : "hello"
1947+
}
1948+
""".data(using: .utf8)!
1949+
1950+
XCTAssertEqual(
1951+
try orderUnstableDecode(JSONSchema.self, from: extensionSchema),
1952+
JSONSchema.all(of: [JSONSchema.string, JSONSchema.number]).with(vendorExtensions: ["x-hello": "hello"])
1953+
)
1954+
}
1955+
1956+
func test_decodeOneOfWithVendorExtension() throws {
1957+
let extensionSchema = """
1958+
{
1959+
"oneOf" : [
1960+
{ "type": "string" },
1961+
{ "type": "number" }
1962+
],
1963+
"x-hello" : "hello"
1964+
}
1965+
""".data(using: .utf8)!
1966+
1967+
XCTAssertEqual(
1968+
try orderUnstableDecode(JSONSchema.self, from: extensionSchema),
1969+
JSONSchema.one(of: [JSONSchema.string, JSONSchema.number]).with(vendorExtensions: ["x-hello": "hello"])
1970+
)
1971+
}
19211972

19221973
func test_encodeExamplesVendorExtension() throws {
19231974
let fragment = JSONSchema.fragment(.init(examples: ["hello"])).with(vendorExtensions: ["x-hello": "hello"])

0 commit comments

Comments
 (0)