Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SR-9641] JSONSerialization inconsistent floating-point conversions #3559

Open
swift-ci opened this issue Jan 11, 2019 · 5 comments
Open

[SR-9641] JSONSerialization inconsistent floating-point conversions #3559

swift-ci opened this issue Jan 11, 2019 · 5 comments

Comments

@swift-ci
Copy link
Contributor

Previous ID SR-9641
Radar rdar://problem/47255325
Original Reporter dbplunkett (JIRA User)
Type Bug
Environment

Xcode 10.1 build 10B61
Swift 4.2.1

Additional Detail from JIRA
Votes 0
Component/s Foundation
Labels Bug
Assignee bendjones (JIRA)
Priority Medium

md5: e796154a189d9afb62080e631baa45e4

Issue Description:

Some floats change when decoded by JSONSerialization. I believe JSONSerialization is supposed to losslessly round-trip all single- and double-precision floats. The problem seems to be in the decoding, because instantiating a number directly from the encoded string doesn't exhibit this problem.

Three example values are below: One that always changes when decoded, one that changes ONLY when decoded as a root value via `allowFragments`, and one that becomes NaN when decoded (therefore failing to decode at all).

let number = NSNumber(value: 0.0003) // changes when decoded
//let number = NSNumber(value: 0.000001) // changes when decoded as a root value
//let number = NSNumber(value: Double.greatestFiniteMagnitude) // changes to NaN when decoded

let encodedArray = try! JSONSerialization.data(withJSONObject: [number])
let encodedNumber = encodedArray.dropFirst().dropLast()

NSNumber(value: Double(String(data: encodedNumber, encoding: .utf8)!)!) == number // this always succeeds

let decodedArray = try! JSONSerialization.jsonObject(with: encodedArray) as! [NSNumber]
let decodedNumber = try! JSONSerialization.jsonObject(with: encodedNumber, options: .allowFragments) as! NSNumber

decodedArray[0] == number
decodedNumber == number
@belkadan
Copy link

0.0003 can't be exactly represented as a float value in the first place, but I guess it shouldn't actually change. cc @phausler and @itaiferber to link with other float serialization bug reports.

@itaiferber
Copy link
Contributor

These are issues with {{NSJSONSerialization}} that we should fix from the Objective-C side. (I can reproduce with transliterated Obj-C code.)

@swift-ci
Copy link
Contributor Author

Comment by Ben D. Jones (JIRA)

Thanks for the radar Itai. I’ll take a look today while a have a bit of time.

@swift-ci
Copy link
Contributor Author

Comment by David Plunkett (JIRA)

@belkadan I debated how explicitly I should call out that it doesn't seem like a misunderstanding of float representation on my part is the problem - but yeah, I realize the literals in my code are not exactly representable. I left them that way for brevity.

@belkadan
Copy link

:-) We've seen enough people skip that first step that I had to say it, but your use of == demonstrates that you're not falling in that trap.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
@shahmishal shahmishal transferred this issue from apple/swift May 5, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants