Fix for [SR-1250] NSJSONSerialization emits non-floating-point numbers as Double (#914)
diff --git a/Foundation/NSJSONSerialization.swift b/Foundation/NSJSONSerialization.swift
index 8e08b85..36120e3 100644
--- a/Foundation/NSJSONSerialization.swift
+++ b/Foundation/NSJSONSerialization.swift
@@ -716,22 +716,25 @@
defer { intEndPointer.deallocate(capacity: 1) }
let doubleEndPointer = UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>.allocate(capacity: 1)
defer { doubleEndPointer.deallocate(capacity: 1) }
-
let intResult = strtol(startPointer, intEndPointer, 10)
let intDistance = startPointer.distance(to: intEndPointer[0]!)
let doubleResult = strtod(startPointer, doubleEndPointer)
let doubleDistance = startPointer.distance(to: doubleEndPointer[0]!)
-
+
guard intDistance > 0 || doubleDistance > 0 else {
return nil
}
-
+
if intDistance == doubleDistance {
return (intResult, intDistance)
}
guard doubleDistance > 0 else {
return nil
}
+
+ if doubleResult == doubleResult.rounded() {
+ return (Int(doubleResult), doubleDistance)
+ }
return (doubleResult, doubleDistance)
}
}
diff --git a/TestFoundation/TestNSJSONSerialization.swift b/TestFoundation/TestNSJSONSerialization.swift
index 33eadcb..0e4e09f 100644
--- a/TestFoundation/TestNSJSONSerialization.swift
+++ b/TestFoundation/TestNSJSONSerialization.swift
@@ -468,7 +468,7 @@
XCTAssertEqual(result?[1] as? Int, -1)
XCTAssertEqual(result?[2] as? Double, 1.3)
XCTAssertEqual(result?[3] as? Double, -1.3)
- XCTAssertEqual(result?[4] as? Double, 1000)
+ XCTAssertEqual(result?[4] as? Int, 1000)
XCTAssertEqual(result?[5] as? Double, 0.001)
}
} catch {
@@ -871,6 +871,7 @@
("test_jsonObjectToOutputStreamInsufficientBuffer", test_jsonObjectToOutputStreamInsufficientBuffer),
("test_booleanJSONObject", test_booleanJSONObject),
("test_serialize_dictionaryWithDecimal", test_serialize_dictionaryWithDecimal),
+ ("test_serializeDecimalNumberJSONObject", test_serializeDecimalNumberJSONObject),
]
}
@@ -1214,6 +1215,22 @@
XCTAssertTrue(JSONSerialization.isValidJSONObject([true]))
}
+ func test_serializeDecimalNumberJSONObject() {
+ let decimalArray = "[12.1,10.0,0.0,0.0001,20,\(Int.max)]"
+ do {
+ let data = decimalArray.data(using: String.Encoding.utf8)
+ let result = try JSONSerialization.jsonObject(with: data!, options: []) as? [Any]
+ XCTAssertEqual(result?[0] as! Double, 12.1)
+ XCTAssertEqual(result?[1] as! Int, 10)
+ XCTAssertEqual(result?[2] as! Int, 0)
+ XCTAssertEqual(result?[3] as! Double, 0.0001)
+ XCTAssertEqual(result?[4] as! Int, 20)
+ XCTAssertEqual(result?[5] as! Int, Int.max)
+ } catch {
+ XCTFail("Failed during serialization")
+ }
+ }
+
fileprivate func createTestFile(_ path: String,_contents: Data) -> String? {
let tempDir = NSTemporaryDirectory() + "TestFoundation_Playground_" + NSUUID().uuidString + "/"
do {