我正在使用AlamoFire调用我的Web服务:
ApiManager.manager.request(.GET, webServiceCallUrl, parameters: ["id": 123])
.validate()
.responseJSON { response in
switch response.result {
case .Success:
print(response.result.value!)
//...
case .Failure:
//...
}
}
我的网络服务返回以下JSON:
{
//...
"InvoiceLines": [{
"Amount": 0.94
}]
}
Alamofire将其视为double而不是十进制数,因此在输出控制台中我会得到:
{
//...
InvoiceLines = (
{
Amount = "0.9399999999999999";
}
);
}
这会导致我的代码中出现舍入误差。
我已在服务器上使用Fiddler检查了Web服务JSON响应,以确认它返回的是0.94。因此,我可以排除服务器的问题,并怀疑
responseJSON
引起了我的问题。我如何使货币值返回正确的
NSDecimalNumber
值?Jim回答/评论后的额外信息:
var stringToTest = "{\"Amount\":0.94}"
var data = stringToTest.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
var object = try NSJSONSerialization.JSONObjectWithData(data!, options: opt)
var a = object["Amount"]
print(a) //"Optional(0.9399999999999999)"
var b = NSDecimalNumber(decimal: (object["Amount"] as! NSNumber).decimalValue)
print(b) //"0.9399999999999999"
如果我将值以JSON字符串的形式传递,那么我就可以得到我想要的结果:
var stringToTest = "{\"Amount\":\"0.94\"}"
var data = stringToTest.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
var object = try NSJSONSerialization.JSONObjectWithData(data!, options: opt)
var c = NSDecimalNumber(string: (object["Amount"] as! String))
print(c) //0.94
然而,我不想对API进行任何更改,因此需要一种将JSON保持在相同格式的解决方案。我的唯一选择是每次四舍五入吗?这似乎不是正确的做法,并且可能会在未来引起舍入问题。
`var a = 0.93 // 0.93` `var b = 0.94 // 0.93999999999` `var c = 0.95 // 0.95`
只是对于某些数字,内部 var 转储例程处理转换为文本时可能会出现问题;可能对于该数字,内部表示为 0.93999999...995,并且存在一个轻微的错误导致 var 转储处理程序向下舍入而不是向上舍入。只要 print() 起作用,您可以忽略它。 - Jim Driscollprint(NSDecimalNumber(double:round(0.94 * 100)).decimalNumberByDividingBy(100))
可以正常工作,而print(NSDecimalNumber(double: 0.94))
则不行。看起来可能存在一些类型推断问题。请注意,前者的内部转储是不准确的,但实际输出是正常的。 - Jim Driscoll