Search code examples
iosjsonswiftdoubledata-conversion

JSON parsing produce incorrect result for Double datatype


I am trying to convert a class object to JSON string to display on screen but Double datatypes are getting wrong values. Here is my code

struct Wallet: Codable {
  var balance: Double
  var limit: Double
  var currency: String
}

func showJSON() {
  let data = Wallet(balance: Double(200.24), limit: Double(5000), currency: "INR")
  let result = convertToJSONString(data)
  print(result!)
}

func convertToJSONString<T: Codable>(_ response: T) -> String? {
  var jsonString: String?
  let jsonEncoder = JSONEncoder()
  jsonEncoder.outputFormatting = .prettyPrinted
  if let data = try? jsonEncoder.encode(response) {
    jsonString = String(data: data, encoding: .utf8)
  }
  return jsonString
}

//function call
showJSON()

And my output is

{
  "balance" : 200.24000000000001,
  "limit" : 5000,
  "currency" : "INR"
}

Check the balance value here, we have provided 200.24 but after conversion it showing as 200.24000000000001. Can someone suggest what needs to be change here to have exact output?

Note* - You can copy paste this code to playground directly, it will work without any modifications.


Solution

  • As @Devid commented above, floating points are not always accurate and conversion from Double or Float to String get impacted.

    So, instate of doing conversion to String we can always hold JSON in Any datatype to print/show.

    Basically, it won't do conversion so values wont get impacted.

    Here, I Just replaced the convertToJSONString function in above implementation like

    func convertToJSONString<T: Codable>(_ response: T) -> Any? {
      var jsonString: Any?
      let jsonEncoder = JSONEncoder()
      jsonEncoder.outputFormatting = .prettyPrinted
      if let data = try? jsonEncoder.encode(response) {
        jsonString = try? JSONSerialization.jsonObject(with: data, options: [])
      }
      return jsonString
    }
    

    used JSONSerialization and getting output as

    {
      balance = "200.24";
      currency = INR;
      limit = 5000;
    }
    

    It is useful to show big and complex JSON with original Double or Float values and to make use of it you can always hold them in relevant datatypes so values wont get impacted.