Skip to content

Commit 2839a10

Browse files
committed
decoupling formatting logic and lazy loading formatter
1. moved format logic out of NSNumber and in to NSJSonSerialization 2. lazy load the formatter to be instantiated if needed 3. create a single format string to work with all formats since we are lazy loading a single formatter
1 parent 8bf5675 commit 2839a10

File tree

3 files changed

+27
-17
lines changed

3 files changed

+27
-17
lines changed

Foundation/NSJSONSerialization.swift

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

10+
import CoreFoundation
11+
1012
#if os(OSX) || os(iOS)
1113
import Darwin
1214
#elseif os(Linux)
@@ -240,6 +242,14 @@ private struct JSONWriter {
240242
let pretty: Bool
241243
let writer: (String?) -> Void
242244

245+
private lazy var numberformatter: CFNumberFormatter = {
246+
let formatter: CFNumberFormatter
247+
formatter = CFNumberFormatterCreate(nil, CFLocaleCopyCurrent(), kCFNumberFormatterNoStyle)
248+
CFNumberFormatterSetProperty(formatter, kCFNumberFormatterMaxFractionDigits, 15._bridgeToObject())
249+
CFNumberFormatterSetFormat(formatter, "0.###############"._cfObject)
250+
return formatter
251+
}()
252+
243253
init(pretty: Bool = false, writer: @escaping (String?) -> Void) {
244254
self.pretty = pretty
245255
self.writer = writer
@@ -298,15 +308,15 @@ private struct JSONWriter {
298308
writer("\"")
299309
}
300310

301-
func serializeNumber(_ num: NSNumber) throws {
311+
mutating func serializeNumber(_ num: NSNumber) throws {
302312
if num.doubleValue.isInfinite || num.doubleValue.isNaN {
303313
throw NSError(domain: NSCocoaErrorDomain, code: NSCocoaError.PropertyListReadCorruptError.rawValue, userInfo: ["NSDebugDescription" : "Number cannot be infinity or NaN"])
304314
}
305315

306316
// Cannot detect type information (e.g. bool) as there is no objCType property on NSNumber in Swift
307317
// So, just print the number
308318

309-
writer(num.serializationString)
319+
writer(serializationString(for: num))
310320
}
311321

312322
mutating func serializeArray(_ array: NSArray) throws {
@@ -389,6 +399,11 @@ private struct JSONWriter {
389399
writer(" ")
390400
}
391401
}
402+
403+
//[SR-2151] https://bugs.swift.org/browse/SR-2151
404+
private mutating func serializationString(for number: NSNumber) -> String {
405+
return CFNumberFormatterCreateStringWithNumber(nil, numberformatter, number._cfObject)._swiftObject
406+
}
392407
}
393408

394409
//MARK: - JSONDeserializer

Foundation/NSNumber.swift

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -450,23 +450,8 @@ open class NSNumber : NSValue {
450450
open override var description: String {
451451
return description(withLocale: nil)
452452
}
453-
454-
//[SR-2151] https://bugs.swift.org/browse/SR-2151
455-
internal var serializationString: String {
456-
let formatter: CFNumberFormatter
457-
formatter = CFNumberFormatterCreate(nil, CFLocaleCopyCurrent(), kCFNumberFormatterNoStyle)
458-
CFNumberFormatterSetProperty(formatter, kCFNumberFormatterMaxFractionDigits, 15._bridgeToObject())
459-
switch CFNumberGetType(_cfObject as CFNumber){
460-
case .floatType, .float32Type, .float64Type, .cgFloatType, .doubleType:
461-
CFNumberFormatterSetFormat(formatter, "0.###############"._cfObject);
462-
default:break
463-
}
464-
return CFNumberFormatterCreateStringWithNumber(nil, formatter, self._cfObject)._swiftObject
465-
}
466453
}
467454

468-
469-
470455
extension CFNumber : _NSBridgable {
471456
typealias NSType = NSNumber
472457
internal var _nsObject: NSType { return unsafeBitCast(self, to: NSType.self) }

TestFoundation/TestNSJSONSerialization.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -691,9 +691,19 @@ extension TestNSJSONSerialization {
691691
XCTAssertEqual(str!, "{\"\(param.0)\":\(param.0._bridgeToObject().intValue)}", "expect that serialized value should not contain trailing zero or decimal as they are whole numbers ")
692692
}
693693
}
694+
695+
func excecute_testWholeNumbersWithIntInput() {
696+
for i in -10..<10 {
697+
let iStr = "\(i)"
698+
let testDict = [iStr : i as AnyObject] as [String : AnyObject]
699+
let str = try? trySerialize(testDict.bridge())
700+
XCTAssertEqual(str!, "{\"\(iStr)\":\(i)}", "expect that serialized value should not contain trailing zero or decimal as they are whole numbers ")
701+
}
702+
}
694703
excecute_testSetLessThanOne()
695704
excecute_testSetGraterThanOne()
696705
excecute_testWholeNumbersWithDoubleAsInput()
706+
excecute_testWholeNumbersWithIntInput()
697707
}
698708

699709
func test_serialize_null() {

0 commit comments

Comments
 (0)