From 7189d44ec4873577eaf406628a003d11f0b73992 Mon Sep 17 00:00:00 2001 From: Brett Jones Date: Fri, 1 Dec 2017 15:04:21 -0800 Subject: [PATCH] Add `from` supporting array of keys with custom transformation --- CHANGELOG.md | 4 +- Sources/Mapper.swift | 21 ++++++++ .../CustomTransformationTests.swift | 52 +++++++++++++++++++ 3 files changed, 76 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 64a1a72..98b795d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,9 @@ ## Enhancements -- None +- Support `from` Array of Fields for Custom Transformation + [Brett Jones](https://github.com/brodney) + [#131](https://github.com/lyft/mapper/pull/131) ## Bug Fixes diff --git a/Sources/Mapper.swift b/Sources/Mapper.swift index ce2adc4..e2b26d2 100644 --- a/Sources/Mapper.swift +++ b/Sources/Mapper.swift @@ -389,6 +389,27 @@ public struct Mapper { throw MapperError.missingFieldError(field: fields.joined(separator: ", ")) } + /// Get a Convertible value from the specified list of fields. This returns the first value produced in + /// order based on the array of fields. + /// + /// - parameter fields: The array of fields to retrieve from the source data + /// - parameter transformation: The transformation function used to create the expected value + /// + /// - throws: MapperError.missingFieldError if none of the fields have an acceptable value. + /// + /// - returns: The value of type T for the given field + public func from(_ fields: [String], transformation: (Any) throws -> T) + throws -> T where T == T.ConvertedType + { + for field in fields { + if let value: T = try? self.from(field, transformation: transformation) { + return value + } + } + + throw MapperError.missingFieldError(field: fields.joined(separator: ", ")) + } + // MARK: - Custom Transformation /// Get a typed value from the given field by using the given transformation diff --git a/Tests/MapperTests/CustomTransformationTests.swift b/Tests/MapperTests/CustomTransformationTests.swift index a3cc7fe..8938924 100644 --- a/Tests/MapperTests/CustomTransformationTests.swift +++ b/Tests/MapperTests/CustomTransformationTests.swift @@ -76,6 +76,58 @@ final class CustomTransformationTests: XCTestCase { } } + func testCustomTransformationArrayOfKeys() { + struct Test: Mappable { + let value: Int + init(map: Mapper) throws { + value = try map.from(["a", "b"], transformation: { thing in + if let a = thing as? Int { + return a + 1 + } + throw MapperError.customError(field: nil, message: "") + }) + } + } + + do { + let test = try Test(map: Mapper(JSON: ["a": "##", "b": 1])) + XCTAssertEqual(test.value, 2) + } catch { + XCTFail("Shouldn't have failed to create Test") + } + } + + func testCustomTransformationArrayOfKeysThrows() { + struct Test: Mappable { + let value: Int + init(map: Mapper) throws { + value = try map.from(["a", "b"], transformation: { _ in + throw MapperError.customError(field: nil, message: "") + }) + } + } + + let test = try? Test(map: Mapper(JSON: ["a": "##", "b": 1])) + XCTAssertNil(test) + } + + func testOptionalCustomTransformationEmptyThrows() { + struct Test: Mappable { + let value: Int + init(map: Mapper) throws { + value = try map.from(["a", "b"], transformation: { thing in + if let a = thing as? Int { + return a + 1 + } + throw MapperError.customError(field: nil, message: "") + }) + } + } + + let test = try? Test(map: Mapper(JSON: [:])) + XCTAssertNil(test) + } + func testOptionalCustomTransformationArrayOfKeys() { struct Test: Mappable { let value: Int?