diff --git a/Sources/AnyCodable/AnyCodable.swift b/Sources/AnyCodable/AnyCodable.swift index 9d4b952..459a174 100644 --- a/Sources/AnyCodable/AnyCodable.swift +++ b/Sources/AnyCodable/AnyCodable.swift @@ -126,6 +126,12 @@ extension AnyCodable: Codable { try container.encodeNil() case let value as NSNumber: try container.encode(value.doubleValue) + case let value as Date: + try container.encode(value) + case let value as URL: + try container.encode(value) + case let value as Encodable: + try value.encode(to: encoder) default: throw EncodingError.invalidValue( value, diff --git a/Sources/AnyCodable/KeyedContainerProtocol+EvaluatingNil.swift b/Sources/AnyCodable/KeyedContainerProtocol+EvaluatingNil.swift index 1df1a74..e087305 100644 --- a/Sources/AnyCodable/KeyedContainerProtocol+EvaluatingNil.swift +++ b/Sources/AnyCodable/KeyedContainerProtocol+EvaluatingNil.swift @@ -19,13 +19,14 @@ public extension KeyedDecodingContainerProtocol { */ public func decodeIfPresentEvaluatingNil(_ type: T.Type, forKey key: Self.Key) throws -> T?? where T: Decodable { - switch try? self.decodeNil(forKey: key) { - case .some(true): - return .some(nil) - case .some(false): - return try self.decodeIfPresent(T.self, forKey: key) - case .none: + guard self.contains(key) else { return nil } + + if try self.decodeNil(forKey: key) { + return .some(nil) + } else { + return try self.decode(T.self, forKey: key) + } } } diff --git a/Tests/AnyCodableTests/AnyCodableTests.swift b/Tests/AnyCodableTests/AnyCodableTests.swift index 872648c..b801659 100644 --- a/Tests/AnyCodableTests/AnyCodableTests.swift +++ b/Tests/AnyCodableTests/AnyCodableTests.swift @@ -52,16 +52,18 @@ class AnyCodableTests: XCTestCase { XCTAssertTrue(dataString.contains("\"double-rounded\":2")) XCTAssertTrue(dataString.contains("\"string\":\"test\"")) XCTAssertTrue(dataString.contains("\"nil\":null")) + XCTAssertTrue(dataString.contains("\"date\":-978307180")) + XCTAssertTrue(dataString.contains("\"url\":\"http:\\/\\/localhost\"")) } func testDecodable() throws { - let data = try JSONSerialization.data(withJSONObject: AnyCodableTests.mockDataStructure) + let data = try JSONEncoder().encode(AnyCodable(AnyCodableTests.mockDataStructure)) let anyCodable = try JSONDecoder().decode(AnyCodable.self, from: data) let any = anyCodable.value as! [String: Any?] - XCTAssertEqual(any["dictionary"] as! [String: String], ["key": "value"]) + XCTAssertEqual((any["dictionary"] as! [String: Any])["key"] as? String, "value") XCTAssertEqual((any["optionalDictionary"] as! [String: Any?])["key"] as? String, "value") XCTAssertNil((any["optionalDictionary"] as! [String: Any?])["nil"]!) XCTAssertEqual(any["array"] as! [String], ["a", "b", "c"]) @@ -85,6 +87,12 @@ class AnyCodableTests: XCTestCase { XCTAssertEqual(any["double-rounded"] as! Int, Int(2)) XCTAssertEqual(any["string"] as! String, "test") XCTAssertNil(any["nil"]!) + XCTAssertEqual(any["decimal"] as! Double, Double(1.23), accuracy: 0.001) + XCTAssertEqual(any["decimalNumber"] as! Double, Double(1.23), accuracy: 0.001) + XCTAssertTrue(any["number-bool"] as! Bool) + XCTAssertEqual(any["number-int"] as! Int, Int(2)) + XCTAssertEqual(any["date"] as! Int, -978307180) + XCTAssertEqual(any["url"] as! String, "http://localhost") } } @@ -114,6 +122,8 @@ extension AnyCodableTests { "decimal": Decimal(1.23), "decimalNumber": NSDecimalNumber(decimal: 1.23), "number-bool": NSNumber(value: 1), - "number-int": NSNumber(value: 2) + "number-int": NSNumber(value: 2), + "date": Date(timeIntervalSince1970: 20.0), + "url": URL(string: "http://localhost")! ] }