I'm trying to perform a HTTP request to a server: the content is a JSON object, which contains a numeric value for the key "amount". If the "amount" is a value with a decimal digit, e.g. 1.6, the request will contain the value 1.6000000000000001, and this value is not accepted by the Server (the api is Java made and the type is a float . I cannot send a String to the server, since the API that receives the data from me can only accept numbers for the "amount". I tried to perform the request with Siesta Framework or with dataTask, but the result is always the same
this is how I create the request (I omitted the less important parts)
let jsonData = try! JSONSerialization.data(withJSONObject: jsonObject) // jsonObject contains the Double value "amount"
let request = URLRequest(url: url)
request.httpBody = jsonData
let task = URLSession.shared.dataTask(with: request)
task.resume()
Without code that fully reproduces the issue, it’s hard to say for sure, but I imagine what you’re seeing is this behavior:
let amount = 1.6 // Double
let jsonObject = ["amount": amount]
let jsonData = try! JSONSerialization.data(withJSONObject: jsonObject)
String(data: jsonData, encoding: String.Encoding.utf8)
Swift Foundation’s JSON serialization always formats numeric values to their full precision — so the double-precision number 1.6 gets formatted as 1.6000000000000001
.
You can and should send a string if the server accepts it:
let amount = "1.6" // String
let jsonObject = ["amount": amount]
let jsonData = try! JSONSerialization.data(withJSONObject: jsonObject)
String(data: jsonData, encoding: String.Encoding.utf8)
Note that a string is the only correct way to send this value if you are dealing with money or anything else where exact values matter: even if you spell it as 1.6
, a standard JSON parser will likely convert it to a floating point on the receiving end.
If you just need to format it with less precision to make it pass validation on the server for some reason, you can embed it in the JSON as a Decimal
instead of a Double
and it will get formatted differently:
let amount = 1.6
let jsonObject = ["amount": Decimal(amount)]
let jsonData = try! JSONSerialization.data(withJSONObject: jsonObject)
String(data: jsonData, encoding: String.Encoding.utf8)
// {"amount":1.6}
You can even manipulate the Decimal
to round to a certain precision.
Note, however, that this does not spare you from floating point precision issues: you are still sending a float according to the JSON spec, and it will still most likely be parsed as a float on the receiving end.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With