Swiftyjson: .doubleValue successfully converts string into Double while .double returns nil

Created on 10 Nov 2017  路  5Comments  路  Source: SwiftyJSON/SwiftyJSON

What did you do?

Pulling JSON from: https://apiv2.bitcoinaverage.com/indices/global/ticker/BTCUSD which currently returns:

{
"ask": "6746.95",
"bid": "6738.92",
"last": "6745.46",
"high": "7331.56",
"low": "6722.81",
"open": {
"hour": "7158.04",
"day": "7158.04",
"week": "7024.12",
"month": "4822.05",
"month_3": "3405.78",
"month_6": "1744.77",
"year": "719.80"
},
"averages": {
"day": "7092.52",
"week": "7113.14",
"month": "6776.50"
},
"volume": "182053.35813936",
"changes": {
"price": {
"hour": "-412.58",
"day": "-412.58",
"week": "-278.66",
"month": "1923.41",
"month_3": "3339.68",
"month_6": "5000.69",
"year": "6025.66"
},
"percent": {
"hour": "-5.76",
"day": "-5.76",
"week": "-3.97",
"month": "39.89",
"month_3": "98.06",
"month_6": "286.61",
"year": "837.13"
}
},
"volume_percent": "79.66",
"timestamp": 1510336968,
"display_timestamp": "2017-11-10 18:02:48"
}

was attempting to extract the "last" value as a double by:

if let lastValue = json["last"].double { print(lastValue) }
// did other things with the lastValue than just print.

What did you expect to happen?

I expected the string would convert successfully as Double? or nil if the data was not available. Using json["last"].doubleValue works.

What actually happened instead?

The typecast failed and my "else" segment of code ran instead.

Environment

List the software versions you're using:

  • SwiftyJSON: 4.0.0
  • Xcode Version: 9.1 (9B55) (Open Xcode; In menubar: Xcode > About Xcode)
  • Swift Version: Xcode.Default (Open Xcode Preferences; Components > Toolchains. If none, use Xcode Default.)

Please also mention which package manager you used and its version. Delete the
other package managers in this list:

  • Cocoapods: 1.3.1 (Use pod --version in Terminal)

Project that demonstrates the issue

https://github.com/Causaelity/SwiftyJSONDoubleBug

Most helpful comment

Forked the code, added the fix and provided some new unit tests, created pull request.

All 5 comments

Looking at your code I think this is because public var numberValue: NSNumber has a .string case where public var number: NSNumber? does not. Adding the following code fixed this problem:

   //Optional number
    public var number: NSNumber? {
        get {
            switch self.type {
            case .string:
                let decimal: NSDecimalNumber? = NSDecimalNumber(string: self.object as? String)
                if decimal == NSDecimalNumber.notANumber {  // indicates parse error
                    return nil
                }
                return decimal
            case .number:
                return self.rawNumber
            case .bool:
                return NSNumber(value: self.rawBool ? 1 : 0)
            default:
                return nil
            }
        }
        set {
            self.object = newValue ?? NSNull()
        }
    }

Forked the code, added the fix and provided some new unit tests, created pull request.

Sounds like this issue is still not merged into v4.1.0 as i'm facing the exact same problem.

Any update on that ?

I'm not sure how they decide what to merge vs not.

Same problem with .bool and .int

Was this page helpful?
0 / 5 - 0 ratings

Related issues

kwstasna picture kwstasna  路  4Comments

amit-bhavsar picture amit-bhavsar  路  5Comments

zxcv740 picture zxcv740  路  6Comments

joernroeder picture joernroeder  路  4Comments

marcheimendinger picture marcheimendinger  路  8Comments