From 8b146e8d5a321311e607ef891962a63d4fdce2ad Mon Sep 17 00:00:00 2001 From: Roger Oba Date: Sun, 13 Jun 2021 02:12:41 -0300 Subject: [PATCH] Add JSEN custom initializer to init from `Any?`. --- .../xcshareddata/xcschemes/JSEN.xcscheme | 94 +++++++++++++++++++ Sources/JSEN.swift | 17 ++++ Tests/JSENTests.swift | 47 +++++++++- 3 files changed, 156 insertions(+), 2 deletions(-) create mode 100644 .swiftpm/xcode/xcshareddata/xcschemes/JSEN.xcscheme diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/JSEN.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/JSEN.xcscheme new file mode 100644 index 0000000..53d4c87 --- /dev/null +++ b/.swiftpm/xcode/xcshareddata/xcschemes/JSEN.xcscheme @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Sources/JSEN.swift b/Sources/JSEN.swift index 6570449..dc9d8a0 100644 --- a/Sources/JSEN.swift +++ b/Sources/JSEN.swift @@ -18,6 +18,23 @@ public enum JSEN : Equatable { /// A null value. case null + /// Attempts to initialize a JSEN instance from an `Any?` value. + init?(from anyValue: Any?) { + switch anyValue { + case let int as Int: self = .int(int) + case let double as Double: self = .double(double) + case let bool as Bool: self = .bool(bool) + case let string as String: self = .string(string) + case let array as [Any]: + let jsenElements: [JSEN] = array.compactMap { JSEN(from: $0) } + self = .array(jsenElements) + case let dictionary as [String:Any]: + let jsenElements: [String:JSEN] = dictionary.compactMapValues { JSEN(from: $0) } + self = .dictionary(jsenElements) + default: return nil + } + } + /// The extracted value from **self**, or **nil** if **self** is a `.null` case. public var valueType: Any? { switch self { diff --git a/Tests/JSENTests.swift b/Tests/JSENTests.swift index 1c0682f..c11891e 100644 --- a/Tests/JSENTests.swift +++ b/Tests/JSENTests.swift @@ -20,7 +20,7 @@ final class JSENTests : XCTestCase { } func test_decodeAsType_withValidTypeFromDictionary_shouldDecode() { - let jsen = JSEN.dictionary([ "key" : "value"]) + let jsen = JSEN.dictionary(["key" : "value"]) let decoded = jsen.decode(as: Model.self) XCTAssertEqual(decoded?.key, "value") } @@ -32,7 +32,7 @@ final class JSENTests : XCTestCase { } func test_decodeAsType_withInvalidType_shouldReturnNil() { - let jsen = JSEN.dictionary(["wrong_key": "value"]) + let jsen = JSEN.dictionary(["wrong_key" : "value"]) let decoded = jsen.decode(as: Model.self, dumpingErrorOnFailure: true) XCTAssertNil(decoded) } @@ -47,4 +47,47 @@ final class JSENTests : XCTestCase { XCTAssertEqual(JSEN.dictionary(["my_key" : "my_value"]).description, #"["my_key": "my_value"]"#) XCTAssertEqual(JSEN.null.description, "null") } + + func test_initializer_withFlatValues_shouldMatchTheExpectedValues() { + let int: Any? = 42 + XCTAssertEqual(JSEN(from: int), .int(42)) + let double: Any? = 42.42 + XCTAssertEqual(JSEN(from: double), .double(42.42)) + let string: Any? = "testing" + XCTAssertEqual(JSEN(from: string), .string("testing")) + let bool: Any? = true + XCTAssertEqual(JSEN(from: bool), .bool(true)) + let array: Any? = [ 42 ] + XCTAssertEqual(JSEN(from: array), .array([42])) + let dictionary: Any? = [ "key" : 42 ] + XCTAssertEqual(JSEN(from: dictionary), .dictionary(["key" : 42])) + } + + func test_initializer_withNestedValues_shouldSucceed() { + let array: Any? = [ + 42, + "42", + true, + [ + 24, + "24", + false, + ], + ] + XCTAssertNotNil(JSEN(from: array)) + let dictionary: Any? = [ + "key" : 42, + "another" : true, + "nested" : [ + "key" : true, + "another" : "yes", + "bool" : false, + "double" : 3.14, + "3rd" : [ + "yup" : "it works", + ] + ] + ] + XCTAssertNotNil(JSEN(from: dictionary)) + } }