diff --git a/Sources/Foundation/JSONDecoder.swift b/Sources/Foundation/JSONDecoder.swift index faa3431631..aef6c2a0f6 100644 --- a/Sources/Foundation/JSONDecoder.swift +++ b/Sources/Foundation/JSONDecoder.swift @@ -197,7 +197,7 @@ open class JSONDecoder { do { var parser = JSONParser(bytes: Array(data)) let json = try parser.parse() - return try JSONDecoderImpl(userInfo: self.userInfo, from: json, codingPath: [], options: self.options).unwrap(as: T.self) + return try JSONDecoderImpl(userInfo: self.userInfo, from: json, codingPath: [], options: self.options).unwrap(as: type) } catch let error as JSONError { throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: [], debugDescription: "The given data was not valid JSON.", underlyingError: error)) } catch { @@ -292,11 +292,11 @@ extension JSONDecoderImpl: Decoder { if type == Decimal.self { return try self.unwrapDecimal() as! T } - if T.self is _JSONStringDictionaryDecodableMarker.Type { - return try self.unwrapDictionary(as: T.self) + if type is _JSONStringDictionaryDecodableMarker.Type { + return try self.unwrapDictionary(as: type) } - return try T(from: self) + return try type.init(from: self) } private func unwrapDate() throws -> Date { @@ -611,8 +611,8 @@ extension JSONDecoderImpl { try decodeFixedWidthInteger() } - func decode(_: T.Type) throws -> T where T: Decodable { - try self.impl.unwrap(as: T.self) + func decode(_ type: T.Type) throws -> T where T: Decodable { + try self.impl.unwrap(as: type) } @inline(__always) private func decodeFixedWidthInteger() throws -> T { @@ -746,9 +746,9 @@ extension JSONDecoderImpl { try decodeFixedWidthInteger(key: key) } - func decode(_: T.Type, forKey key: K) throws -> T where T: Decodable { + func decode(_ type: T.Type, forKey key: K) throws -> T where T: Decodable { let newDecoder = try decoderForKey(key) - return try newDecoder.unwrap(as: T.self) + return try newDecoder.unwrap(as: type) } func nestedContainer(keyedBy type: NestedKey.Type, forKey key: K) throws @@ -926,9 +926,9 @@ extension JSONDecoderImpl { try decodeFixedWidthInteger() } - mutating func decode(_: T.Type) throws -> T where T: Decodable { - let newDecoder = try decoderForNextElement(ofType: T.self) - let result = try newDecoder.unwrap(as: T.self) + mutating func decode(_ type: T.Type) throws -> T where T: Decodable { + let newDecoder = try decoderForNextElement(ofType: type) + let result = try newDecoder.unwrap(as: type) // Because of the requirement that the index not be incremented unless // decoding the desired result type succeeds, it can not be a tail call. diff --git a/Tests/Foundation/Tests/TestJSONEncoder.swift b/Tests/Foundation/Tests/TestJSONEncoder.swift index 3fc3451898..ab74ac4a7f 100644 --- a/Tests/Foundation/Tests/TestJSONEncoder.swift +++ b/Tests/Foundation/Tests/TestJSONEncoder.swift @@ -474,6 +474,24 @@ class TestJSONEncoder : XCTestCase { XCTFail("Caught error during decoding empty super decoder: \(error)") } } + + func test_childTypeDecoder() { + class BaseTestType: Decodable { } + class ChildTestType: BaseTestType { } + + func dynamicTestType() -> BaseTestType.Type { + return ChildTestType.self + } + + let decoder = JSONDecoder() + do { + let testType = dynamicTestType() + let instance = try decoder.decode(testType, from: Data(#"{}"#.utf8)) + XCTAssertTrue(instance is ChildTestType) + } catch { + XCTFail("Caught error during decoding empty super decoder: \(error)") + } + } // MARK: - Test encoding and decoding of built-in Codable types func test_codingOfBool() { @@ -1562,6 +1580,7 @@ extension TestJSONEncoder { ("test_nestedContainerCodingPaths", test_nestedContainerCodingPaths), ("test_superEncoderCodingPaths", test_superEncoderCodingPaths), ("test_notFoundSuperDecoder", test_notFoundSuperDecoder), + ("test_childTypeDecoder", test_childTypeDecoder), ("test_codingOfBool", test_codingOfBool), ("test_codingOfNil", test_codingOfNil), ("test_codingOfInt8", test_codingOfInt8),