Skip to content

Commit d122f98

Browse files
committed
[JSONSerialization] Always use reference types to match Darwin behavior
1 parent fb20a32 commit d122f98

File tree

3 files changed

+26
-45
lines changed

3 files changed

+26
-45
lines changed

Foundation/JSONEncoder.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -859,7 +859,7 @@ open class JSONDecoder {
859859
/// - throws: `DecodingError.dataCorrupted` if values requested from the payload are corrupted, or if the given data is not valid JSON.
860860
/// - throws: An error if any value throws an error during decoding.
861861
open func decode<T : Decodable>(_ type: T.Type, from data: Data) throws -> T {
862-
let topLevel = try JSONSerialization.jsonObject(with: data, options: [.useReferenceNumericTypes])
862+
let topLevel = try JSONSerialization.jsonObject(with: data, options: [])
863863
let decoder = _JSONDecoder(referencing: topLevel, options: self.options)
864864
return try T(from: decoder)
865865
}

Foundation/JSONSerialization.swift

Lines changed: 10 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,16 @@ import CoreFoundation
1717

1818
extension JSONSerialization {
1919
public struct ReadingOptions : OptionSet {
20-
public let rawValue : UInt
20+
public let rawValue: UInt
2121
public init(rawValue: UInt) { self.rawValue = rawValue }
2222

2323
public static let mutableContainers = ReadingOptions(rawValue: 1 << 0)
2424
public static let mutableLeaves = ReadingOptions(rawValue: 1 << 1)
2525
public static let allowFragments = ReadingOptions(rawValue: 1 << 2)
26-
internal static let useReferenceNumericTypes = ReadingOptions(rawValue: 1 << 15)
2726
}
2827

2928
public struct WritingOptions : OptionSet {
30-
public let rawValue : UInt
29+
public let rawValue: UInt
3130
public init(rawValue: UInt) { self.rawValue = rawValue }
3231

3332
public static let prettyPrinted = WritingOptions(rawValue: 1 << 0)
@@ -806,6 +805,7 @@ private struct JSONReader {
806805
|| (byte >= 0x41 && byte <= 0x46)
807806
|| (byte >= 0x61 && byte <= 0x66)
808807
}
808+
809809
func parseCodeUnit(_ input: Index) -> (UTF16.CodeUnit, Index)? {
810810
let hexParser = takeMatching(isHexChr)
811811
guard let (result, index) = hexParser([], input).flatMap(hexParser).flatMap(hexParser).flatMap(hexParser),
@@ -820,6 +820,7 @@ private struct JSONReader {
820820
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, // 0...9
821821
0x2E, 0x2D, 0x2B, 0x45, 0x65, // . - + E e
822822
]
823+
823824
func parseNumber(_ input: Index, options opt: JSONSerialization.ReadingOptions) throws -> (Any, Index)? {
824825
func parseTypedNumber(_ address: UnsafePointer<UInt8>, count: Int) -> (Any, IndexDistance)? {
825826
let temp_buffer_size = 64
@@ -837,32 +838,15 @@ private struct JSONReader {
837838
let doubleResult = strtod(startPointer, doubleEndPointer)
838839
let doubleDistance = startPointer.distance(to: doubleEndPointer[0]!)
839840

840-
guard intDistance > 0 || doubleDistance > 0 else {
841-
return nil
842-
}
843-
844-
let shouldUseReferenceType = opt.contains(.useReferenceNumericTypes)
845-
841+
guard doubleDistance > 0 else { return nil }
846842
if intDistance == doubleDistance {
847-
return (shouldUseReferenceType ? NSNumber(value: intResult) : intResult,
848-
intDistance)
843+
return (NSNumber(value: intResult), intDistance)
849844
}
850-
guard doubleDistance > 0 else {
851-
return nil
852-
}
853-
854-
if doubleResult == doubleResult.rounded() {
855-
return (shouldUseReferenceType ? NSNumber(value: Int(doubleResult)) : Int(doubleResult),
856-
doubleDistance)
857-
}
858-
859-
return (shouldUseReferenceType ? NSNumber(value: doubleResult) : doubleResult,
860-
doubleDistance)
845+
return (NSNumber(value: doubleResult), doubleDistance)
861846
}
862847
}
863848

864-
if source.encoding == String.Encoding.utf8 {
865-
849+
if source.encoding == .utf8 {
866850
return parseTypedNumber(source.buffer.baseAddress!.advanced(by: input), count: source.buffer.count - input).map { return ($0.0, input + $0.1) }
867851
}
868852
else {
@@ -872,7 +856,6 @@ private struct JSONReader {
872856
numberCharacters.append(ascii)
873857
index = nextIndex
874858
}
875-
876859
numberCharacters.append(0)
877860

878861
return numberCharacters.withUnsafeBufferPointer {
@@ -887,12 +870,10 @@ private struct JSONReader {
887870
return (value, parser)
888871
}
889872
else if let parser = try consumeASCIISequence("true", input: input) {
890-
let result: Any = opt.contains(.useReferenceNumericTypes) ? NSNumber(value: true) : true
891-
return (result, parser)
873+
return (NSNumber(value: true), parser)
892874
}
893875
else if let parser = try consumeASCIISequence("false", input: input) {
894-
let result: Any = opt.contains(.useReferenceNumericTypes) ? NSNumber(value: false) : false
895-
return (result, parser)
876+
return (NSNumber(value: false), parser)
896877
}
897878
else if let parser = try consumeASCIISequence("null", input: input) {
898879
return (NSNull(), parser)

TestFoundation/TestJSONSerialization.swift

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,6 @@
77
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
88
//
99

10-
// Exposing internal ReadingOptions for tests.
11-
extension JSONSerialization.ReadingOptions {
12-
fileprivate static let useReferenceNumericTypes = JSONSerialization.ReadingOptions(rawValue: 1 << 15)
13-
}
14-
1510
class TestJSONSerialization : XCTestCase {
1611

1712
let supportedEncodings: [String.Encoding] = [
@@ -477,7 +472,7 @@ extension TestJSONSerialization {
477472
XCTFail("Unable to convert string to data")
478473
return
479474
}
480-
let result = try getjsonObjectResult(data, objectType, options: [.useReferenceNumericTypes]) as? [Any]
475+
let result = try getjsonObjectResult(data, objectType) as? [Any]
481476
XCTAssertEqual(result?[0] as? NSNumber, true)
482477
XCTAssertEqual(result?[1] as? NSNumber, false)
483478
XCTAssertEqual(result?[2] as? String, "hello")
@@ -492,7 +487,7 @@ extension TestJSONSerialization {
492487

493488
//MARK: - Number parsing
494489
func deserialize_numbers(objectType: ObjectType) {
495-
let subject = "[1, -1, 1.3, -1.3, 1e3, 1E-3]"
490+
let subject = "[1, -1, 1.3, -1.3, 1e3, 1E-3, 10]"
496491

497492
do {
498493
for encoding in supportedEncodings {
@@ -501,33 +496,38 @@ extension TestJSONSerialization {
501496
return
502497
}
503498
let result = try getjsonObjectResult(data, objectType) as? [Any]
504-
XCTAssertEqual(result?[0] as? Int, 1)
505-
XCTAssertEqual(result?[1] as? Int, -1)
506-
XCTAssertEqual(result?[2] as? Double, 1.3)
507-
XCTAssertEqual(result?[3] as? Double, -1.3)
508-
XCTAssertEqual(result?[4] as? Int, 1000)
499+
XCTAssertEqual(result?[0] as? Int, 1)
500+
XCTAssertEqual(result?[1] as? Int, -1)
501+
XCTAssertEqual(result?[2] as? Double, 1.3)
502+
XCTAssertEqual(result?[3] as? Double, -1.3)
503+
XCTAssertEqual(result?[4] as? Int, 1000)
509504
XCTAssertEqual(result?[5] as? Double, 0.001)
505+
XCTAssertEqual(result?[6] as? Int, 10)
506+
XCTAssertEqual(result?[6] as? Double, 10.0)
510507
}
511508
} catch {
512509
XCTFail("Unexpected error: \(error)")
513510
}
514511
}
512+
515513
func deserialize_numbers_as_reference_types(objectType: ObjectType) {
516-
let subject = "[1, -1, 1.3, -1.3, 1e3, 1E-3]"
514+
let subject = "[1, -1, 1.3, -1.3, 1e3, 1E-3, 10]"
517515

518516
do {
519517
for encoding in supportedEncodings {
520518
guard let data = subject.data(using: encoding) else {
521519
XCTFail("Unable to convert string to data")
522520
return
523521
}
524-
let result = try getjsonObjectResult(data, objectType, options: [.useReferenceNumericTypes]) as? [Any]
522+
let result = try getjsonObjectResult(data, objectType) as? [Any]
525523
XCTAssertEqual(result?[0] as? NSNumber, 1)
526524
XCTAssertEqual(result?[1] as? NSNumber, -1)
527525
XCTAssertEqual(result?[2] as? NSNumber, 1.3)
528526
XCTAssertEqual(result?[3] as? NSNumber, -1.3)
529527
XCTAssertEqual(result?[4] as? NSNumber, 1000)
530528
XCTAssertEqual(result?[5] as? NSNumber, 0.001)
529+
XCTAssertEqual(result?[6] as? NSNumber, 10)
530+
XCTAssertEqual(result?[6] as? NSNumber, 10.0)
531531
}
532532
} catch {
533533
XCTFail("Unexpected error: \(error)")
@@ -1449,7 +1449,7 @@ extension TestJSONSerialization {
14491449
}
14501450
do {
14511451
let data = decimalArray.data(using: String.Encoding.utf8)
1452-
let result = try JSONSerialization.jsonObject(with: data!, options: [.useReferenceNumericTypes]) as? [Any]
1452+
let result = try JSONSerialization.jsonObject(with: data!, options: []) as? [Any]
14531453
XCTAssertEqual(result?[0] as! NSNumber, 12.1)
14541454
XCTAssertEqual(result?[1] as! NSNumber, 10)
14551455
XCTAssertEqual(result?[2] as! NSNumber, 0)

0 commit comments

Comments
 (0)