diff --git a/Foundation/JSONEncoder.swift b/Foundation/JSONEncoder.swift index bdcd479091..9da3572bee 100644 --- a/Foundation/JSONEncoder.swift +++ b/Foundation/JSONEncoder.swift @@ -859,7 +859,7 @@ open class JSONDecoder { /// - throws: `DecodingError.dataCorrupted` if values requested from the payload are corrupted, or if the given data is not valid JSON. /// - throws: An error if any value throws an error during decoding. open func decode(_ type: T.Type, from data: Data) throws -> T { - let topLevel = try JSONSerialization.jsonObject(with: data, options: [.useReferenceNumericTypes]) + let topLevel = try JSONSerialization.jsonObject(with: data, options: []) let decoder = _JSONDecoder(referencing: topLevel, options: self.options) return try T(from: decoder) } diff --git a/Foundation/JSONSerialization.swift b/Foundation/JSONSerialization.swift index 20f35d5320..a54c5c75f0 100644 --- a/Foundation/JSONSerialization.swift +++ b/Foundation/JSONSerialization.swift @@ -17,17 +17,16 @@ import CoreFoundation extension JSONSerialization { public struct ReadingOptions : OptionSet { - public let rawValue : UInt + public let rawValue: UInt public init(rawValue: UInt) { self.rawValue = rawValue } public static let mutableContainers = ReadingOptions(rawValue: 1 << 0) public static let mutableLeaves = ReadingOptions(rawValue: 1 << 1) public static let allowFragments = ReadingOptions(rawValue: 1 << 2) - internal static let useReferenceNumericTypes = ReadingOptions(rawValue: 1 << 15) } public struct WritingOptions : OptionSet { - public let rawValue : UInt + public let rawValue: UInt public init(rawValue: UInt) { self.rawValue = rawValue } public static let prettyPrinted = WritingOptions(rawValue: 1 << 0) @@ -806,6 +805,7 @@ private struct JSONReader { || (byte >= 0x41 && byte <= 0x46) || (byte >= 0x61 && byte <= 0x66) } + func parseCodeUnit(_ input: Index) -> (UTF16.CodeUnit, Index)? { let hexParser = takeMatching(isHexChr) guard let (result, index) = hexParser([], input).flatMap(hexParser).flatMap(hexParser).flatMap(hexParser), @@ -820,6 +820,7 @@ private struct JSONReader { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, // 0...9 0x2E, 0x2D, 0x2B, 0x45, 0x65, // . - + E e ] + func parseNumber(_ input: Index, options opt: JSONSerialization.ReadingOptions) throws -> (Any, Index)? { func parseTypedNumber(_ address: UnsafePointer, count: Int) -> (Any, IndexDistance)? { let temp_buffer_size = 64 @@ -837,32 +838,15 @@ private struct JSONReader { let doubleResult = strtod(startPointer, doubleEndPointer) let doubleDistance = startPointer.distance(to: doubleEndPointer[0]!) - guard intDistance > 0 || doubleDistance > 0 else { - return nil - } - - let shouldUseReferenceType = opt.contains(.useReferenceNumericTypes) - + guard doubleDistance > 0 else { return nil } if intDistance == doubleDistance { - return (shouldUseReferenceType ? NSNumber(value: intResult) : intResult, - intDistance) + return (NSNumber(value: intResult), intDistance) } - guard doubleDistance > 0 else { - return nil - } - - if doubleResult == doubleResult.rounded() { - return (shouldUseReferenceType ? NSNumber(value: Int(doubleResult)) : Int(doubleResult), - doubleDistance) - } - - return (shouldUseReferenceType ? NSNumber(value: doubleResult) : doubleResult, - doubleDistance) + return (NSNumber(value: doubleResult), doubleDistance) } } if source.encoding == .utf8 { - return parseTypedNumber(source.buffer.baseAddress!.advanced(by: input), count: source.buffer.count - input).map { return ($0.0, input + $0.1) } } else { @@ -872,7 +856,6 @@ private struct JSONReader { numberCharacters.append(ascii) index = nextIndex } - numberCharacters.append(0) return numberCharacters.withUnsafeBufferPointer { @@ -887,12 +870,10 @@ private struct JSONReader { return (value, parser) } else if let parser = try consumeASCIISequence("true", input: input) { - let result: Any = opt.contains(.useReferenceNumericTypes) ? NSNumber(value: true) : true - return (result, parser) + return (NSNumber(value: true), parser) } else if let parser = try consumeASCIISequence("false", input: input) { - let result: Any = opt.contains(.useReferenceNumericTypes) ? NSNumber(value: false) : false - return (result, parser) + return (NSNumber(value: false), parser) } else if let parser = try consumeASCIISequence("null", input: input) { return (NSNull(), parser) diff --git a/TestFoundation/TestJSONSerialization.swift b/TestFoundation/TestJSONSerialization.swift index c11f311d77..220c253143 100644 --- a/TestFoundation/TestJSONSerialization.swift +++ b/TestFoundation/TestJSONSerialization.swift @@ -7,11 +7,6 @@ // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // -// Exposing internal ReadingOptions for tests. -extension JSONSerialization.ReadingOptions { - fileprivate static let useReferenceNumericTypes = JSONSerialization.ReadingOptions(rawValue: 1 << 15) -} - class TestJSONSerialization : XCTestCase { let supportedEncodings: [String.Encoding] = [ @@ -477,7 +472,7 @@ extension TestJSONSerialization { XCTFail("Unable to convert string to data") return } - let result = try getjsonObjectResult(data, objectType, options: [.useReferenceNumericTypes]) as? [Any] + let result = try getjsonObjectResult(data, objectType) as? [Any] XCTAssertEqual(result?[0] as? NSNumber, true) XCTAssertEqual(result?[1] as? NSNumber, false) XCTAssertEqual(result?[2] as? String, "hello") @@ -492,7 +487,7 @@ extension TestJSONSerialization { //MARK: - Number parsing func deserialize_numbers(objectType: ObjectType) { - let subject = "[1, -1, 1.3, -1.3, 1e3, 1E-3]" + let subject = "[1, -1, 1.3, -1.3, 1e3, 1E-3, 10]" do { for encoding in supportedEncodings { @@ -501,19 +496,22 @@ extension TestJSONSerialization { return } let result = try getjsonObjectResult(data, objectType) as? [Any] - XCTAssertEqual(result?[0] as? Int, 1) - XCTAssertEqual(result?[1] as? Int, -1) - XCTAssertEqual(result?[2] as? Double, 1.3) - XCTAssertEqual(result?[3] as? Double, -1.3) - XCTAssertEqual(result?[4] as? Int, 1000) + XCTAssertEqual(result?[0] as? Int, 1) + XCTAssertEqual(result?[1] as? Int, -1) + XCTAssertEqual(result?[2] as? Double, 1.3) + XCTAssertEqual(result?[3] as? Double, -1.3) + XCTAssertEqual(result?[4] as? Int, 1000) XCTAssertEqual(result?[5] as? Double, 0.001) + XCTAssertEqual(result?[6] as? Int, 10) + XCTAssertEqual(result?[6] as? Double, 10.0) } } catch { XCTFail("Unexpected error: \(error)") } } + func deserialize_numbers_as_reference_types(objectType: ObjectType) { - let subject = "[1, -1, 1.3, -1.3, 1e3, 1E-3]" + let subject = "[1, -1, 1.3, -1.3, 1e3, 1E-3, 10]" do { for encoding in supportedEncodings { @@ -521,13 +519,15 @@ extension TestJSONSerialization { XCTFail("Unable to convert string to data") return } - let result = try getjsonObjectResult(data, objectType, options: [.useReferenceNumericTypes]) as? [Any] + let result = try getjsonObjectResult(data, objectType) as? [Any] XCTAssertEqual(result?[0] as? NSNumber, 1) XCTAssertEqual(result?[1] as? NSNumber, -1) XCTAssertEqual(result?[2] as? NSNumber, 1.3) XCTAssertEqual(result?[3] as? NSNumber, -1.3) XCTAssertEqual(result?[4] as? NSNumber, 1000) XCTAssertEqual(result?[5] as? NSNumber, 0.001) + XCTAssertEqual(result?[6] as? NSNumber, 10) + XCTAssertEqual(result?[6] as? NSNumber, 10.0) } } catch { XCTFail("Unexpected error: \(error)") @@ -1449,7 +1449,7 @@ extension TestJSONSerialization { } do { let data = decimalArray.data(using: String.Encoding.utf8) - let result = try JSONSerialization.jsonObject(with: data!, options: [.useReferenceNumericTypes]) as? [Any] + let result = try JSONSerialization.jsonObject(with: data!, options: []) as? [Any] XCTAssertEqual(result?[0] as! NSNumber, 12.1) XCTAssertEqual(result?[1] as! NSNumber, 10) XCTAssertEqual(result?[2] as! NSNumber, 0)