1

A simple function that parse json variable and returns a float.

func parseMyFloat(jsonString: String) -> Float? {
    if let data = jsonString.data(using: String.Encoding.utf8, allowLossyConversion: true),
        let parsedJSON = try? JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.allowFragments) as? [String : Any] {
        if let parsedJSON = parsedJSON {
            return parsedJSON["myFloat"] as? Float
        }
    }
    return nil
} 

Now if i try this.

print(parseMyFloat(jsonString: "{\"myFloat\":23.2322998046875}"))
// output: 23.2322998

output is fine but if I change 23.2322998046875 value to 23.2322998046 func returns nil.

print(parseMyFloat(jsonString: "{\"myFloat\":23.2322998}"))
// output: nil

Then I tried casting Any to Float which doesn't work.

let dic:[String : Any] = ["float1" : 23.2322998046875, "float2" : 23.2322998]
print(dic["float1"] as? Float) // prints nil
print(dic["float2"] as? Float) // prints nil

I have lots of float in my code, so after migrating to swift 4.1 I am having this issue.

Should I change all Float's to Double's ?? And 23.2322998046875 why works and why not 23.2322998??

Bilal
  • 18,478
  • 8
  • 57
  • 72
  • 1
    For a partial answer please see https://stackoverflow.com/questions/49607492/cast-any-to-float-always-fails-in-swift4-1/49703477#49703477 – vadian Apr 12 '18 at 10:16
  • Possible duplicate of [Unexpected behavior when casting an NSNumber to Float](https://stackoverflow.com/questions/49688983/unexpected-behavior-when-casting-an-nsnumber-to-float) – Martin R Apr 12 '18 at 10:54
  • @MartinR can you please suggest any work around? Or only option is to change all the floats to doubles? Or i add special checks for floots and use floatValue method of NSNumber? I just reverted back to swift 4 just because of this issue. There are lots of flaot parsing in our project. Thanks – Bilal Apr 12 '18 at 12:19
  • 1
    @Bilal: Did you try this https://stackoverflow.com/a/49642539/1187415 ? – Martin R Apr 12 '18 at 12:29
  • @MartinR Yeah I have tried that and it works too. But I'm worried because I have to modify lots of code in lots of classes. It's looks like I don't have any other option :( – Bilal Apr 12 '18 at 12:40
  • @Bilal: Yes, I think so (and I am inclined to close this as a duplicate of https://stackoverflow.com/a/49642539/1187415). – Martin R Apr 12 '18 at 13:08
  • @MartinR sure you can close it. One last thing, any explanation about why `23.2322998046875` works and why `23.2322998` doesn't work. Thanks. – Bilal Apr 12 '18 at 13:13

1 Answers1

1

If you want to keep your function as it is and don't want to modify the return value to Double, you can simply parse the JSON value as Double to avoid the issue of casting Any to Float as explained in the comments and then convert the Double to Float before returning it.

func parseMyFloat(jsonString: String) -> Float? {
    if let data = jsonString.data(using: String.Encoding.utf8, allowLossyConversion: true), let parsedJSON = (try? JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.allowFragments)) as? [String : Any], let myDouble = parsedJSON["myFloat"] as? Double {
            return Float(myDouble)
    }
    return nil
}

parseMyFloat(jsonString: "{\"myFloat\":23.2322998046875}") //23.2323998
parseMyFloat(jsonString: "{\"myFloat\":23.2322998}") //23.2323998
Dávid Pásztor
  • 51,403
  • 9
  • 85
  • 116
  • 1
    Does that have an advantage over `(parsedJSON["myFloat"] as? NSNumber)?.floatValue` (as suggested in https://stackoverflow.com/a/49642539/1187415)? – Martin R Apr 12 '18 at 13:07
  • @MartinR I don't think so, I posted my solution as an answer rather than a comment to show OP how they can avoid having to change any code outside the function's scope – Dávid Pásztor Apr 12 '18 at 13:14
  • Thanks, Actually code in the question was just a sample code for the question to simplify the problem. But Thanks. – Bilal Apr 12 '18 at 13:15