János
János

Reputation: 35116

Unable to bridge NSNumber to Float in JSON parsing

Get this error:

Fatal error: Unable to bridge NSNumber to Float. What is the problem?

enter image description here

enter image description here

This is the original message, it is float and not string.

{\"name\":\"Tomas\",\"gender\":\"male\",\"probability\":0.99,\"count\":594}

enter image description here

Upvotes: 14

Views: 7184

Answers (4)

smakus
smakus

Reputation: 1437

Some inside baseball here:

When swift is casting a floating point number from json to float, it has some kind of validation that makes sure the number lands on a terminating fractional value that the float data type can support.

E.g. if your value was 0.25 (1/4th), 0.875 (7/8ths), etc., it would not give you an error.

If your value does not fall on one of these terminating fractions (e.g. 0.33), it assumes some data could be lost to the lack of precision, and it throws an error.

If you don't care about the potential data loss, here is one way to convert the value to a float without much worry:

Float(jsonDictionary["jsonDictionaryKey"] as! Double)

Upvotes: -1

Jean-Baptiste Yunès
Jean-Baptiste Yunès

Reputation: 36431

You have many different types of numbers in Swift/Foundation. Your NSKeyValueCoding has been set as instance of NSNumber (see excerpt of JSON serialization documentation below) so you need to read as is, and then ask to convert this NSNumber as Float if needed:

if let n = d.value(forKey: "probability") as? NSNumber {
    let f = n.floatValue
}

JSONSerialization documentation says:

A Foundation object that may be converted to JSON must have the following properties:

  • The top level object is an NSArray or NSDictionary.
  • All objects are instances of NSString, NSNumber, NSArray, NSDictionary, or NSNull.
  • All dictionary keys are instances of NSString.
  • Numbers are not NaN or infinity.

Upvotes: 33

Gereon
Gereon

Reputation: 17872

I would recommend ditching the dictionary representation entirely and moving to a type-safe parser using Decodable:

struct User: Decodable {
    let name: String
    let gender: String
    let probability: Float
    let count: Int
}

let str = "{ \"name\": \"Tomas\", \"gender\": \"male\", \"probability\":0.99, \"count\": 594 }"
let data = str.data(using: .utf8)!
do {
  let user = try JSONDecoder().decode(User.self, from: data)
} catch {
  // handle errors
}

Upvotes: 0

vadian
vadian

Reputation: 285210

You are using the wrong API.

Don’t use KVC (valueForKey) unless you really need KVC.

For getting a dictionary value use always key subscription (or objectForKey)

if let probability = d["probability"] as? Float {
    print(probability)
}

Upvotes: 0

Related Questions