From 19794e57d75c9c66c532a04b2b573722a363ebb7 Mon Sep 17 00:00:00 2001 From: Peter Schumacher Date: Tue, 7 Jun 2016 15:14:15 +0200 Subject: [PATCH 1/4] added flatend custom Array unboxing --- Sources/Unbox.swift | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Sources/Unbox.swift b/Sources/Unbox.swift index 7773277..0b88c6d 100644 --- a/Sources/Unbox.swift +++ b/Sources/Unbox.swift @@ -407,6 +407,13 @@ public class Unboxer { return try Unboxer(dictionary: dictionary, context: context).performCustomUnboxingWithClosure(closure) } + /// Perform custom unboxing on an array of dictionaries, executing a closure with a new Unboxer for each one, discarding elements producing errors + public static func performFlattenedCustomUnboxingWithArray(array: [UnboxableDictionary], context: Any? = nil, closure: Unboxer throws -> T?) throws -> [T] { + return array.flatMap { (dictionary) -> T? in + return try? self.performCustomUnboxingWithDictionary(dictionary, context: context, closure: closure) + } + } + /// Perform custom unboxing on an array of dictionaries, executing a closure with a new Unboxer for each one, or throw an UnboxError public static func performCustomUnboxingWithArray(array: [UnboxableDictionary], context: Any? = nil, closure: Unboxer throws -> T?) throws -> [T] { var unboxedArray = [T]() From c1724ed0a065accb38c7e9311fe524236a532ef9 Mon Sep 17 00:00:00 2001 From: Peter Schumacher Date: Tue, 7 Jun 2016 15:38:35 +0200 Subject: [PATCH 2/4] added Test --- Tests/UnboxTests.swift | 44 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/Tests/UnboxTests.swift b/Tests/UnboxTests.swift index 1319193..58cb172 100644 --- a/Tests/UnboxTests.swift +++ b/Tests/UnboxTests.swift @@ -907,6 +907,50 @@ class UnboxTests: XCTestCase { XCTFail("Unexpected error thrown: \(error)") } } + + func testFlattenedCustomUnboxingFromArrayWithMultipleClasses() { + struct ModelA { + let int: Int + } + + struct ModelB { + let string: String + } + + let array: [UnboxableDictionary] = [ + [ + "type" : "A", + "int" : 22 + ], + [ + "type" : "B", + "WrongKey" : "hello" + ] + ] + + do { + let unboxed: [Any] = try Unboxer.performFlattenedCustomUnboxingWithArray(array, closure: { + let unboxer = $0 + let type = unboxer.unbox("type") as String + + switch type { + case "A": + return ModelA(int: unboxer.unbox("int")) + case "B": + return ModelB(string: unboxer.unbox("string")) + default: + XCTFail() + } + + return nil + }) + + XCTAssertEqual((unboxed.first as! ModelA).int, 22) + XCTAssertTrue(unboxed.count == 1) + } catch { + XCTFail("Unexpected error thrown: \(error)") + } + } } private func UnboxTestDictionaryWithAllRequiredKeysWithValidValues(nested: Bool) -> UnboxableDictionary { From 9035fa35bf6bd892315a2c664839f4cbb8935db7 Mon Sep 17 00:00:00 2001 From: Peter Schumacher Date: Tue, 7 Jun 2016 15:46:22 +0200 Subject: [PATCH 3/4] flattened unboxing doesn't throw anymore --- Sources/Unbox.swift | 2 +- Tests/UnboxTests.swift | 38 +++++++++++++++++--------------------- 2 files changed, 18 insertions(+), 22 deletions(-) diff --git a/Sources/Unbox.swift b/Sources/Unbox.swift index 0b88c6d..5ac3d90 100644 --- a/Sources/Unbox.swift +++ b/Sources/Unbox.swift @@ -408,7 +408,7 @@ public class Unboxer { } /// Perform custom unboxing on an array of dictionaries, executing a closure with a new Unboxer for each one, discarding elements producing errors - public static func performFlattenedCustomUnboxingWithArray(array: [UnboxableDictionary], context: Any? = nil, closure: Unboxer throws -> T?) throws -> [T] { + public static func performFlattenedCustomUnboxingWithArray(array: [UnboxableDictionary], context: Any? = nil, closure: Unboxer throws -> T?) -> [T] { return array.flatMap { (dictionary) -> T? in return try? self.performCustomUnboxingWithDictionary(dictionary, context: context, closure: closure) } diff --git a/Tests/UnboxTests.swift b/Tests/UnboxTests.swift index 58cb172..eea70d8 100644 --- a/Tests/UnboxTests.swift +++ b/Tests/UnboxTests.swift @@ -928,28 +928,24 @@ class UnboxTests: XCTestCase { ] ] - do { - let unboxed: [Any] = try Unboxer.performFlattenedCustomUnboxingWithArray(array, closure: { - let unboxer = $0 - let type = unboxer.unbox("type") as String - - switch type { - case "A": - return ModelA(int: unboxer.unbox("int")) - case "B": - return ModelB(string: unboxer.unbox("string")) - default: - XCTFail() - } - - return nil - }) + let unboxed: [Any] = Unboxer.performFlattenedCustomUnboxingWithArray(array, closure: { + let unboxer = $0 + let type = unboxer.unbox("type") as String - XCTAssertEqual((unboxed.first as! ModelA).int, 22) - XCTAssertTrue(unboxed.count == 1) - } catch { - XCTFail("Unexpected error thrown: \(error)") - } + switch type { + case "A": + return ModelA(int: unboxer.unbox("int")) + case "B": + return ModelB(string: unboxer.unbox("string")) + default: + XCTFail() + } + + return nil + }) + + XCTAssertEqual((unboxed.first as! ModelA).int, 22) + XCTAssertTrue(unboxed.count == 1) } } From 69f394f01842c16e5b8a549ef8bd6597316cbb35 Mon Sep 17 00:00:00 2001 From: Peter Schumacher Date: Mon, 13 Jun 2016 13:50:17 +0200 Subject: [PATCH 4/4] changed to allowInvalidElements parameter convention --- Sources/Unbox.swift | 23 +++++++++-------------- Tests/UnboxTests.swift | 42 +++++++++++++++++++++++------------------- 2 files changed, 32 insertions(+), 33 deletions(-) diff --git a/Sources/Unbox.swift b/Sources/Unbox.swift index 5ac3d90..bd205ff 100644 --- a/Sources/Unbox.swift +++ b/Sources/Unbox.swift @@ -407,23 +407,18 @@ public class Unboxer { return try Unboxer(dictionary: dictionary, context: context).performCustomUnboxingWithClosure(closure) } - /// Perform custom unboxing on an array of dictionaries, executing a closure with a new Unboxer for each one, discarding elements producing errors - public static func performFlattenedCustomUnboxingWithArray(array: [UnboxableDictionary], context: Any? = nil, closure: Unboxer throws -> T?) -> [T] { - return array.flatMap { (dictionary) -> T? in - return try? self.performCustomUnboxingWithDictionary(dictionary, context: context, closure: closure) - } - } - /// Perform custom unboxing on an array of dictionaries, executing a closure with a new Unboxer for each one, or throw an UnboxError - public static func performCustomUnboxingWithArray(array: [UnboxableDictionary], context: Any? = nil, closure: Unboxer throws -> T?) throws -> [T] { - var unboxedArray = [T]() + public static func performCustomUnboxingWithArray(array: [UnboxableDictionary], context: Any? = nil, allowInvalidElements: Bool = false, closure: Unboxer throws -> T?) throws -> [T] { - for dictionary in array { - let unboxed = try self.performCustomUnboxingWithDictionary(dictionary, context: context, closure: closure) - unboxedArray.append(unboxed) + if allowInvalidElements { + return array.flatMap { (dictionary) -> T? in + return try? self.performCustomUnboxingWithDictionary(dictionary, context: context, closure: closure) + } + } else { + return try array.map { (dictionary) -> T in + return try self.performCustomUnboxingWithDictionary(dictionary, context: context, closure: closure) + } } - - return unboxedArray } /// Perform custom unboxing using an Unboxer (created from NSData) passed to a closure, or throw an UnboxError diff --git a/Tests/UnboxTests.swift b/Tests/UnboxTests.swift index eea70d8..3081ffd 100644 --- a/Tests/UnboxTests.swift +++ b/Tests/UnboxTests.swift @@ -908,7 +908,7 @@ class UnboxTests: XCTestCase { } } - func testFlattenedCustomUnboxingFromArrayWithMultipleClasses() { + func testCustomUnboxingFromArrayWithMultipleClassesAndAllowedInvalid() { struct ModelA { let int: Int } @@ -927,26 +927,30 @@ class UnboxTests: XCTestCase { "WrongKey" : "hello" ] ] - - let unboxed: [Any] = Unboxer.performFlattenedCustomUnboxingWithArray(array, closure: { - let unboxer = $0 - let type = unboxer.unbox("type") as String - - switch type { - case "A": - return ModelA(int: unboxer.unbox("int")) - case "B": - return ModelB(string: unboxer.unbox("string")) - default: - XCTFail() - } + do { + let unboxed: [Any] = try Unboxer.performCustomUnboxingWithArray(array, allowInvalidElements: true, closure: { + let unboxer = $0 + let type = unboxer.unbox("type") as String + + switch type { + case "A": + return ModelA(int: unboxer.unbox("int")) + case "B": + return ModelB(string: unboxer.unbox("string")) + default: + XCTFail() + } + + return nil + }) - return nil - }) - - XCTAssertEqual((unboxed.first as! ModelA).int, 22) - XCTAssertTrue(unboxed.count == 1) + XCTAssertEqual((unboxed.first as! ModelA).int, 22) + XCTAssertTrue(unboxed.count == 1) + } catch { + XCTFail("Unexpected error thrown: \(error)") + } } + } private func UnboxTestDictionaryWithAllRequiredKeysWithValidValues(nested: Bool) -> UnboxableDictionary {