From cd6b05f26a48221707e588ec45b0c33ead4766d0 Mon Sep 17 00:00:00 2001 From: Yunpeng Li Date: Thu, 3 Aug 2023 21:05:56 +0800 Subject: [PATCH 1/2] Fix JSONDecoder.decode(_,from:) behavior --- Sources/Foundation/JSONDecoder.swift | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) 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. From 6c3ff7ee61248a5163f5bd447fd9611f9e3ca093 Mon Sep 17 00:00:00 2001 From: Yunpeng Li Date: Mon, 7 Aug 2023 13:35:05 +0800 Subject: [PATCH 2/2] add 'test_childTypeDecoder' to test 'JSONDecoder.decode(_,from:)' --- Tests/Foundation/Tests/TestJSONEncoder.swift | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) 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),