From 6273fedb2792c4263cc536120182f8906b87b161 Mon Sep 17 00:00:00 2001 From: Dave Camp Date: Thu, 22 Jun 2017 13:21:59 -0700 Subject: [PATCH] Change `parseEntity` to not wrap errors thrown by Decoders and Decodables in a `ParserError`. This allows the decoding process to report error conditions discovered in the JSON (e.g. embedded error codes) as something other than parsing errors. Added Decoder and Decodable tests to validate that custom errors can be caught as expected. --- CHANGELOG.md | 9 ++++++++- Source/Parser.swift | 9 +++++++-- Tests/DecodableTests.swift | 19 +++++++++++++++++++ Tests/DecoderTests.swift | 19 +++++++++++++++++++ Tests/Decoders.swift | 6 ++++++ Tests/ModelObjects.swift | 12 ++++++++++++ 6 files changed, 71 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9cddfa0..3027176 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. #### 2.x Releases -* `2.2.x` Releases = [2.2.0](#220) | [2.2.1](#221) +* `2.2.x` Releases = [2.2.0](#220) | [2.2.1](#221) | [2.2.2](#222) * `2.1.x` Releases = [2.1.0](#210) * `2.0.x` Releases = [2.0.0](#200) @@ -16,6 +16,13 @@ All notable changes to this project will be documented in this file. --- +## [2.2.2](https://github.com/Nike-Inc/Elevate/releases/tag/2.2.2) + +Released on 2017-06-22. All issues associated with this milestone can be found using this +[filter](https://github.com/Nike-Inc/Elevate/milestone/5?closed=1). + +--- + ## [2.2.1](https://github.com/Nike-Inc/Elevate/releases/tag/2.2.1) Released on 2017-02-09. All issues associated with this milestone can be found using this diff --git a/Source/Parser.swift b/Source/Parser.swift index f806510..e4d22c3 100644 --- a/Source/Parser.swift +++ b/Source/Parser.swift @@ -43,12 +43,15 @@ public class Parser { /// - closure: Defines the property list for the parser via the passed in `Schema` instance. /// /// - Returns: The parsed entity as a Dictionary. + /// + /// - Throws: `ParserError` for parsing related errors or `Error`s thrown by custom `Decodable` and `Decoder` implementations. public class func parseEntity(data: Data, closure: (Schema) -> Void) throws -> [String: Any] { let result: [String: Any] + let json: Any + // A JSONSerialization error will be converted to ParserError do { - let json = try JSONSerialization.jsonObject(with: data, options: []) - result = try parseEntity(json: json, closure: closure) + json = try JSONSerialization.jsonObject(with: data, options: []) } catch { if error is ParserError { throw error @@ -60,6 +63,8 @@ public class Parser { } } + result = try parseEntity(json: json, closure: closure) + return result } diff --git a/Tests/DecodableTests.swift b/Tests/DecodableTests.swift index b2152ff..ed12928 100644 --- a/Tests/DecodableTests.swift +++ b/Tests/DecodableTests.swift @@ -392,6 +392,25 @@ class DecodableTestCase: BaseTestCase { decodableErrorTest(type: [String: String].self, value: "1") } + func testThatThrownCustomErrorsCanBeCaught() { + do { + // Given + let data = loadJSONDataForFileNamed("PropertyTypesTest") + + // When + let _: ErrorThrowingDecodable = try Elevate.decodeObject(from: data) + + XCTFail("Decoding unexpectedly succeeded.") + } catch let error as NSError { + // Then + XCTAssertEqual(error.domain, "Decodable Test Error", "Error domain did not match expected value.") + XCTAssertEqual(error.code, 42, "Error code did not match expected value.") + } catch { + XCTFail("Parser error was of incorrect type.") + + } + } + // MARK: - Private - Helper Methods private func decodableErrorTest(type: Decodable.Type, value: Any) { diff --git a/Tests/DecoderTests.swift b/Tests/DecoderTests.swift index a97c2d6..7fc2441 100644 --- a/Tests/DecoderTests.swift +++ b/Tests/DecoderTests.swift @@ -261,4 +261,23 @@ class DateDecoderTestCase: BaseTestCase { XCTFail("Parser error was of incorrect type") } } + + func testThatThrownCustomErrorsCanBeCaught() { + do { + // Given + let data = loadJSONDataForFileNamed("PropertyTypesTest") + + // When + let _: ErrorThrowingDecodable = try Elevate.decodeObject(from: data, with: ErrorThrowingDecoder()) + + XCTFail("Decoding unexpectedly succeeded.") + } catch let error as NSError { + // Then + XCTAssertEqual(error.domain, "Decoder Test Error", "Error domain did not match expected value.") + XCTAssertEqual(error.code, 42, "Error code did not match expected value.") + } catch { + XCTFail("Parser error was of incorrect type.") + + } + } } diff --git a/Tests/Decoders.swift b/Tests/Decoders.swift index f54cdf7..557ced0 100644 --- a/Tests/Decoders.swift +++ b/Tests/Decoders.swift @@ -46,3 +46,9 @@ struct TestObjectDecoder: Decoder { ) } } + +struct ErrorThrowingDecoder: Decoder { + func decode(_ object: Any) throws -> Any { + throw NSError(domain: "Decoder Test Error", code: 42, userInfo: nil) + } +} diff --git a/Tests/ModelObjects.swift b/Tests/ModelObjects.swift index a81b53d..27c3f1f 100644 --- a/Tests/ModelObjects.swift +++ b/Tests/ModelObjects.swift @@ -96,3 +96,15 @@ extension InvalidDecodable: Decodable { invalid = entity[invalidKeyPath] as! String } } + +// MARK: - + +struct ErrorThrowingDecodable {} + +// MARK: - + +extension ErrorThrowingDecodable: Decodable { + init(json: Any) throws { + throw NSError(domain: "Decodable Test Error", code: 42, userInfo: nil) + } +}