【问题标题】:Sending a numeric value in http request with swift, adds 000000000000001 to the actual value使用 swift 在 http 请求中发送数值,将 000000000000001 添加到实际值
【发布时间】:2018-01-20 06:40:47
【问题描述】:

我正在尝试向服务器执行 HTTP 请求:内容是 JSON 对象,其中包含键“amount”的数值。如果“金额”是带有小数位的值,例如1.6、请求中会包含值 1.6000000000000001,服务器不接受这个值(api是Java制作的,类型是浮点数。我不能向服务器发送字符串,因为从我那里接收数据的API只能接受“金额”的数字"。我尝试使用 Siesta Framework 或 dataTask 执行请求,但结果始终相同

这就是我创建请求的方式(我省略了不太重要的部分)

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()

【问题讨论】:

  • 你能包含一些代码吗
  • 这是在编程中使用浮点值的一个基本问题stackoverflow.com/questions/2100490/…
  • 是的。但这仍然不能解决我的问题,对不起
  • 您正在尝试修复客户端上的服务器问题。服务器上的 java 代码应该正确解析该值。如果它不这样做,那就是服务器问题。如果你需要精确,你应该使用字符串(和 java BigDecimal)。
  • 谢谢。但不幸的是,我不拥有该项目的服务器端,此时所有者无法更改该部分

标签: ios swift siesta-swift


【解决方案1】:

如果没有完全重现问题的代码,很难确定,但我想您看到的是这种行为:

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 的 JSON 序列化始终将数值格式化为其全精度 - 因此双精度数 1.6 被格式化为 1.6000000000000001

方案一:发送字符串

如果服务器接受,你可以并且应该发送一个字符串:

let amount = "1.6"  // String
let jsonObject = ["amount": amount]
let jsonData = try! JSONSerialization.data(withJSONObject: jsonObject)
String(data: jsonData, encoding: String.Encoding.utf8)

请注意,如果您处理的是金钱或其他任何对精确值很重要的东西,字符串是发送此值的唯一正确方法:即使您将其拼写为 1.6,标准 JSON解析器可能会在接收端将其转换为浮点数。

解决方案 2:使用 Decimal 更改格式

如果您只是需要以较低的精度对其进行格式化以使其由于某种原因通过服务器上的验证,您可以将其作为Decimal 而不是Double 嵌入到 JSON 中,它将得到不同的格式:

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}

您甚至可以操纵Decimal 以四舍五入到某个精度。

但是请注意,这并不能让您避免浮点精度问题:您仍在根据 JSON 规范发送浮点数,并且它仍然很可能在接收端被解析为浮点数。

【讨论】:

  • 这是一个很好的答案,谢谢。无论如何,我通过解决方法解决了这个问题:我使用 THIS 库 github.com/peheje/JsonSerializerSwift 将 json 对象转换为 json 字符串:此序列化程序创建一个 json 字符串,而不将 1.6 格式化为 1.6000000000000001 并将值保持为 Double;然后我将该 json 字符串转换为数据,并使用 Siesta 框架发送数据。这可能不是最好的,但它确实有效。再次感谢!
  • 如果格式是您所追求的全部,将小数直接放入您的字典应该也适用于 Siesta。
  • 用十进制我解决了。很好很简单,谢谢你,保罗!
【解决方案2】:

如果没有看到您的代码,很难提供帮助,但是,要检查的一件事是您是否使用 NumberFormatter 来确保您的值得到正确的舍入。假设你从 UITextField 中提取数字,那么你需要这样的东西:

let numberFormatter = NumberFormatter()
numberFormatter.numberStyle = .decimal
if let textValue = textField.value {
    var amount = numberFormatter.number(from: textValue)
}

【讨论】:

  • 感谢您的帮助,我将把我的代码的相关部分添加到我的问题中添加更多详细信息
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-11-05
  • 1970-01-01
  • 2014-08-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多