-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Closed
Labels
Description
| Previous ID | SR-7195 |
| Radar | None |
| Original Reporter | @florianreinhart |
| Type | Bug |
| Status | Resolved |
| Resolution | Done |
Environment
Swift 4.0.3, macOS 10.13.3 and Ubuntu 16.04
Additional Detail from JIRA
| Votes | 0 |
| Component/s | Foundation |
| Labels | Bug |
| Assignee | None |
| Priority | Medium |
md5: e38af2c3f6bfc9b1fe10fcfba2bf9763
relates to:
- SR-5961 JSONSerialization does not properly convert
1.1
Issue Description:
`JSONSerialization` and thus `JSONEncoder` encode floating point values in a different way on Linux than on Darwin. This can cause a loss of precision and decoding a different value than the one that was encoded on Linux.
Running the following code demonstrates the issue.
import Foundation
let value1 = 7.7087009966199993
let value2 = 7.7087009966200002
// Encode using JSONSerialization
do {
print("Encoding using JSONSerialization")
let dict1 = ["value": value1]
let dict2 = ["value": value2]
let jsonData1 = try! JSONSerialization.data(withJSONObject: dict1)
let jsonData2 = try! JSONSerialization.data(withJSONObject: dict2)
let jsonString1 = String(decoding: jsonData1, as: UTF8.self)
let jsonString2 = String(decoding: jsonData2, as: UTF8.self)
print("json1 is: \(jsonString1). Dump of input value follows.")
dump(dict1)
print("json2 is: \(jsonString2). Dump of input value follows.")
dump(dict2)
// Decode using JSONSerialization
print("\nDecoding using JSONSerialization")
let decodedDict1 = try! JSONSerialization.jsonObject(with: jsonData1) as! [String : Double]
let decodedDict2 = try! JSONSerialization.jsonObject(with: jsonData2) as! [String : Double]
print("decoded dictionary 1 is\(dict1 == decodedDict1 ? "" : " not") equal to the input. Dump of decoded value follows.")
dump(decodedDict1)
print("decoded dictionary 2 is\(dict2 == decodedDict2 ? "" : " not") equal to the input. Dump of decoded value follows.")
dump(decodedDict2)
}
struct DoubleWrapper: Equatable, Codable {
let value: Double
static func ==(lhs: DoubleWrapper, rhs: DoubleWrapper) -> Bool {
return lhs.value == rhs.value
}
}
do {
// Encode using JSONEncoder
print("\n\n\nEncoding using JSONEncoder")
let wrappedValue1 = DoubleWrapper(value: value1)
let wrappedValue2 = DoubleWrapper(value: value2)
let jsonEncoder = JSONEncoder()
let jsonData1 = try! jsonEncoder.encode(wrappedValue1)
let jsonData2 = try! jsonEncoder.encode(wrappedValue2)
let jsonString1 = String(decoding: jsonData1, as: UTF8.self)
let jsonString2 = String(decoding: jsonData2, as: UTF8.self)
print("json1 is: \(jsonString1). Dump of input follows.")
dump(wrappedValue1)
print("json2 is: \(jsonString2). Dump of input follows.")
dump(wrappedValue2)
// Decode using JSONDecoder
print("\nDecoding using JSONDecoder")
let jsonDecoder = JSONDecoder()
let decodedWrappedValue1 = try! jsonDecoder.decode(DoubleWrapper.self, from: jsonData1)
let decodedWrappedValue2 = try! jsonDecoder.decode(DoubleWrapper.self, from: jsonData2)
print("decoded value 1 is\(wrappedValue1 == decodedWrappedValue1 ? "" : " not") equal to the input. Dump of decoded value follows.")
dump(decodedWrappedValue1)
print("decoded value 1 is\(wrappedValue2 == decodedWrappedValue2 ? "" : " not") equal to the input. Dump of decoded value follows.")
dump(decodedWrappedValue2)
}Swift 4.0.3 on macOS 10.13.3 produces the following output and encodes and decodes all values as expected.
Encoding using JSONSerialization
json1 is: {"value":7.7087009966199993}. Dump of input value follows.
▿ 1 key/value pair
▿ (2 elements)
- key: "value"
- value: 7.7087009966199993
json2 is: {"value":7.7087009966200002}. Dump of input value follows.
▿ 1 key/value pair
▿ (2 elements)
- key: "value"
- value: 7.7087009966200002
Decoding using JSONSerialization
decoded dictionary 1 is equal to the input. Dump of decoded value follows.
▿ 1 key/value pair
▿ (2 elements)
- key: "value"
- value: 7.7087009966199993
decoded value 1 is equal to the input. Dump of decoded value follows.
▿ 1 key/value pair
▿ (2 elements)
- key: "value"
- value: 7.7087009966200002
Encoding using JSONEncoder
json1 is: {"value":7.7087009966199993}. Dump of input follows.
▿ DoubleTable.DoubleWrapper
- value: 7.7087009966199993
json2 is: {"value":7.7087009966200002}. Dump of input follows.
▿ DoubleTable.DoubleWrapper
- value: 7.7087009966200002
Decoding using JSONDecoder
decoded value 1 is equal to the input. Dump of decoded value follows.
▿ DoubleTable.DoubleWrapper
- value: 7.7087009966199993
decoded value 1 is equal to the input. Dump of decoded value follows.
▿ DoubleTable.DoubleWrapper
- value: 7.7087009966200002
And Swift 4.0.3 on Ubuntu 16.04. Both input double values are encoded as 7.70870099662 in the resulting JSON.
Encoding using JSONSerialization
json1 is: {"value":7.70870099662}. Dump of input value follows.
▿ 1 key/value pair
▿ (2 elements)
- key: "value"
- value: 7.7087009966199993
json2 is: {"value":7.70870099662}. Dump of input value follows.
▿ 1 key/value pair
▿ (2 elements)
- key: "value"
- value: 7.7087009966200002
Decoding using JSONSerialization
decoded dictionary 1 is not equal to the input. Dump of decoded value follows.
▿ 1 key/value pair
▿ (2 elements)
- key: "value"
- value: 7.7087009966200002
decoded value 1 is equal to the input. Dump of decoded value follows.
▿ 1 key/value pair
▿ (2 elements)
- key: "value"
- value: 7.7087009966200002
Encoding using JSONEncoder
json1 is: {"value":7.70870099662}. Dump of input follows.
▿ test.DoubleWrapper
- value: 7.7087009966199993
json2 is: {"value":7.70870099662}. Dump of input follows.
▿ test.DoubleWrapper
- value: 7.7087009966200002
Decoding using JSONDecoder
decoded value 1 is not equal to the input. Dump of decoded value follows.
▿ test.DoubleWrapper
- value: 7.7087009966200002
decoded value 1 is equal to the input. Dump of decoded value follows.
▿ test.DoubleWrapper
- value: 7.7087009966200002