diff --git a/Sources/SwaggerSwiftML/Models/Operation.swift b/Sources/SwaggerSwiftML/Models/Operation.swift index 8122bbf..cdbf112 100644 --- a/Sources/SwaggerSwiftML/Models/Operation.swift +++ b/Sources/SwaggerSwiftML/Models/Operation.swift @@ -63,7 +63,7 @@ public struct Operation: Decodable { } else if let parameter = try? parameterContainer.decode(Parameter.self) { params.append(.node(parameter)) } else { - fatalError("Unknown object") + throw UnknownObject() } } self.parameters = params @@ -84,3 +84,5 @@ public struct Operation: Decodable { // self.security = try con.decodeIfPresent(SecurityRequirement.self, forKey: .security) } } + +struct UnknownObject: Error { } diff --git a/Sources/SwaggerSwiftML/Models/Parameter.swift b/Sources/SwaggerSwiftML/Models/Parameter.swift index 104b059..b561b8b 100644 --- a/Sources/SwaggerSwiftML/Models/Parameter.swift +++ b/Sources/SwaggerSwiftML/Models/Parameter.swift @@ -64,22 +64,57 @@ public struct Parameter: Decodable { case "array": let uniqueItems = try container.decodeIfPresent(Bool.self, forKey: .uniqueItems) let collectionFormat = (try container.decodeIfPresent(CollectionFormat.self, forKey: .collectionFormat)) ?? .csv - let items = try container.decode(Items.self, forKey: .items) - type = .array(items, collectionFormat: collectionFormat, maxItems: maxItems, minItems: minItems, uniqueItems: uniqueItems ?? false) + + if let items = try? container.decode(Items.self, forKey: .items) { + type = .array( + .node(items), + collectionFormat: collectionFormat, + maxItems: maxItems, + minItems: minItems, + uniqueItems: uniqueItems ?? false + ) + } else if let reference = try? container.decode(Reference.self, forKey: .items) { + type = .array( + .reference(reference.ref), + collectionFormat: collectionFormat, + maxItems: maxItems, + minItems: minItems, + uniqueItems: uniqueItems ?? false + ) + } else { + throw InvalidArrayType() + } + case "boolean": type = .boolean case "file": type = .file case "integer": - type = .integer(format: format, maximum: maximum, exclusiveMaximum: exclusiveMaximum, minimum: minimum, exclusiveMinimum: exclusiveMinimum, multipleOf: multipleOf) + type = .integer( + format: format, + maximum: maximum, + exclusiveMaximum: exclusiveMaximum, + minimum: minimum, + exclusiveMinimum: exclusiveMinimum, + multipleOf: multipleOf + ) case "number": - type = .number(format: format, maximum: maximum, exclusiveMaximum: exclusiveMaximum, minimum: minimum, exclusiveMinimum: exclusiveMinimum, multipleOf: multipleOf) + type = .number( + format: format, + maximum: maximum, + exclusiveMaximum: exclusiveMaximum, + minimum: minimum, + exclusiveMinimum: exclusiveMinimum, + multipleOf: multipleOf + ) case "string": - type = .string(format: format, - enumValues: enumeration, - maxLength: maxLength, - minLength: minLength, - pattern: pattern) + type = .string( + format: format, + enumValues: enumeration, + maxLength: maxLength, + minLength: minLength, + pattern: pattern + ) default: type = nil } @@ -107,3 +142,5 @@ public struct Parameter: Decodable { } } } + +struct InvalidArrayType: Error { } diff --git a/Sources/SwaggerSwiftML/Models/ParameterType.swift b/Sources/SwaggerSwiftML/Models/ParameterType.swift index a0076cd..3d31655 100644 --- a/Sources/SwaggerSwiftML/Models/ParameterType.swift +++ b/Sources/SwaggerSwiftML/Models/ParameterType.swift @@ -3,6 +3,6 @@ public indirect enum ParameterType { case number(format: DataFormat?, maximum: Int?, exclusiveMaximum: Bool?, minimum: Int?, exclusiveMinimum: Bool?, multipleOf: Int?) case integer(format: DataFormat?, maximum: Int?, exclusiveMaximum: Bool?, minimum: Int?, exclusiveMinimum: Bool?, multipleOf: Int?) case boolean - case array(Items, collectionFormat: CollectionFormat, maxItems: Int?, minItems: Int?, uniqueItems: Bool) + case array(Node, collectionFormat: CollectionFormat, maxItems: Int?, minItems: Int?, uniqueItems: Bool) case file } diff --git a/Sources/SwaggerSwiftML/Models/Schema.swift b/Sources/SwaggerSwiftML/Models/Schema.swift index 4e8506c..1a2e782 100644 --- a/Sources/SwaggerSwiftML/Models/Schema.swift +++ b/Sources/SwaggerSwiftML/Models/Schema.swift @@ -81,6 +81,8 @@ public struct Schema: Decodable { if typeString == nil { if container.contains(.properties) || container.contains(.allOf) { typeString = "object" + } else if container.contains(.items) { + typeString = "array" } else { throw SwaggerError.failedToParse(description: "Failed to parse type without type information. The type has no properties or allOf defined and so it cant be an object. The object has these properties: \(container.allKeys.map { $0.rawValue }.joined(separator: ", "))", codingPath: container.codingPath) } diff --git a/Tests/SwaggerSwiftMLTests/Parameter/array_with_ref.yaml b/Tests/SwaggerSwiftMLTests/Parameter/array_with_ref.yaml new file mode 100644 index 0000000..fb815a8 --- /dev/null +++ b/Tests/SwaggerSwiftMLTests/Parameter/array_with_ref.yaml @@ -0,0 +1,6 @@ +in: query +name: paramName +required: true +type: array +items: + $ref: "#/definitions/SomeType" diff --git a/Tests/SwaggerSwiftMLTests/Parameter/formdata_param.yaml b/Tests/SwaggerSwiftMLTests/Parameter/formdata_param.yaml index efc947f..07bd82a 100644 --- a/Tests/SwaggerSwiftMLTests/Parameter/formdata_param.yaml +++ b/Tests/SwaggerSwiftMLTests/Parameter/formdata_param.yaml @@ -2,3 +2,4 @@ name: avatar in: formData required: true type: file + diff --git a/Tests/SwaggerSwiftMLTests/ParameterTests.swift b/Tests/SwaggerSwiftMLTests/ParameterTests.swift index e016d64..01d18f0 100644 --- a/Tests/SwaggerSwiftMLTests/ParameterTests.swift +++ b/Tests/SwaggerSwiftMLTests/ParameterTests.swift @@ -62,4 +62,14 @@ final class ParameterTests: XCTestCase { // XCTAssertEqual(parameter.location, .body) } + + func testArrayWithRef() { + let basicFileUrl = Bundle.module.url(forResource: "Parameter/array_with_ref", withExtension: "yaml") + + let fileContents = try! String(contentsOf: basicFileUrl!, encoding: .utf8) + + _ = try! YAMLDecoder().decode(Parameter.self, from: fileContents) + + // XCTAssertEqual(parameter.location, .body) + } }