Pataquer
Pataquer

Reputation: 303

JSON Conversion value from string to float

I have a Json (received as text) that I convert it like this:

if let jsonData = raw.data(using: String.Encoding.utf8) {
   if let json = try JSONSerialization.jsonObject(with: jsonData, options: .allowFragments) {
      let products = json["products"] as! [Dictionary<String, AnyObject>]

Products contains an array of products (also json), where I have keys which value can be String, Float, Double... one key has a value that it can be any kind of number.

This field when it is received on text from endpoint looks like this: \"min_size\":\"0.01\" but also can have values like \"min_size\":\"1\", or \"min_size\":\"0.001\". After my json conversion looks like this (printing using po):

▿ 1 : 2 elements
  - key : "min_size"
  - value : 1

Or

▿ 15 : 2 elements
  - key : "min_size"
  - value : 0.01

But then, when I'm trying to access it on my code (I want to read it as a float, independently if it is a 1 or a 0.01), I get this:

let k = item["min_size"] // contains > ▿ Optional<Any> - some : 0.01
let i = item["min_size"] as? Float // contains > nil
let j = item["min_size"] as? Int // contains > nil

let y = item["min_size"] as? NSString // contains > "0.01"
let z = y!.floatValue // contains > "0.009999997"

I'm new on Swift, and I don't understand what's going on here.

Any idea what I'm doing wrong?

Upvotes: 4

Views: 1459

Answers (2)

Eahzo
Eahzo

Reputation: 21

Your dictionary has a value type of AnyObject and your JSON min_size value is a String, you could convert String into a Float and if it does not exist provide a default value:

let y = Float(item["min_size"] as? String ?? "0") ?? 0

Upvotes: 2

Pataquer
Pataquer

Reputation: 303

Based on suggestions that are on comments, solution that I implemented is:

let min_size = (item["min_size"] as? String ?? "").convertFromJSONStringToFloat()

where I have two extensions for String and Float

extension String {
    func convertFromJSONStringToFloat() -> Float? {
        let partNumber = self.split(separator: ".")
        return (Float(self)?.roundToDecimal((partNumber.count > 1) ? partNumber[1].count : 1))!
    }
}

extension Float {
    func roundToDecimal(_ fractionDigits: Int) -> Float {
        let multiplier = pow(10, Double(fractionDigits))
        return Float((Double(self) * multiplier) / multiplier)
    }
}

Upvotes: 2

Related Questions