Skip to content

Fix #79908: json_decode decodes negative zero as positive zero #7234

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

Closed
wants to merge 3 commits into from

Conversation

cmb69
Copy link
Member

@cmb69 cmb69 commented Jul 13, 2021

While the JSON standard knows only numbers (i.e. it doesn't distinguish
between int and float), and does not mention negative zero at all, PHP
makes that distinction, so a negative zero should be parsed as such,
even if the number is not otherwise designated as a float.

While the JSON standard knows only numbers (i.e. it doesn't distinguish
between int and float), and does not mention negative zero at all, PHP
makes that distinction, so a negative zero should be parsed as such,
even if the number is not otherwise designated as a float.
@cmb69 cmb69 added the Bug label Jul 13, 2021
@cmb69
Copy link
Member Author

cmb69 commented Jul 13, 2021

PHP makes that distinction

To be clear: PHP distinguishes between int and float; it does not parse -0 as negative zero, though.

@nikic
Copy link
Member

nikic commented Jul 13, 2021

I'm not sure this is the right way to go about it. I think it would make more sense to special case negative zero to JSON encode as -0.0, but keep parsing of -0 as-is.

I checked the Python and Ruby JSON implementations, and they both decode -0.0 as negative zero and -0 as integer zero.

cmb69 added 2 commits July 13, 2021 14:30
Encoding a negative zero as `-0` is likely to loose the sign when
decoding (at least it does with `json_decode()`).  Therefore, we encode
it as if `JSON_PRESERVE_ZERO_FRACTION` was specified, i.e. as `-0.0`.
@cmb69
Copy link
Member Author

cmb69 commented Jul 13, 2021

Might indeed be the better solution. New fix pushed.

@cmb69 cmb69 closed this in 717f1ed Jul 13, 2021
@cmb69 cmb69 deleted the cmb/79908 branch July 13, 2021 13:35
@bukka
Copy link
Member

bukka commented Jul 19, 2021

@cmb69 I'm not sure if I understand what is being fixed here. There has been explicitly RFC for this: https://wiki.php.net/rfc/json_preserve_fractional_part . Basically anyone who wants to preserve zero fraction (which logically includes -0.0 and 0.0) should use JSON_PRESERVE_ZERO_FRACTION. I think this makes it inconsistent with other numbers. Am I missing anything?

@cmb69
Copy link
Member Author

cmb69 commented Jul 19, 2021

@bukka, it is not about preserving the fraction, but about the sign. As it was, a negative 0 lost its sign after roundtrip: var_dump(json_decode(json_encode(-0.))); // int(0). That does not happen for other (negative) numbers.

@bukka
Copy link
Member

bukka commented Jul 19, 2021

And that's kind of expected because it will be int so there's no difference between -0.0 and 0.0. If you do var_dump(json_decode(json_encode(-1.)));, then it's int(-1). It just seems inconsistent that -0.0 is the only zero fraction that actually produce float. I think if someone really needs this sort of identity, they should just use JSON_PRESERVE_ZERO_FRACTION.

@cmb69
Copy link
Member Author

cmb69 commented Jul 19, 2021

That was my first reaction to the bug report as well; however, this case is somewhat special, since without JSON_PRESERVE_ZERO_FRACTION you never loose precision, but you loose the sign. I'm also fine with my original patch or even to close the ticket as WONTFIX. We just need consensus about what to do. :)

@bukka
Copy link
Member

bukka commented Jul 19, 2021

After reading the bug, I think it would make more sense to do

encode (float) (-0.0) as "0" without JSON_PRESERVE_ZERO_FRACTION
encode (float) (-0.0) as "-0.0" with JSON_PRESERVE_ZERO_FRACTION

The first part is basically what V8 (NodeJS) does:

> JSON.stringify(JSON.parse('-0.0'))
'0'

Although I don't see it as a bug so it should just target master. Unless there's something really broken (which is not in this case), changes in json encoding should not go to bug fixing releases as it might do more harm than good (e.g. might cause change of content after minor update which might not be expected).

@cmb69
Copy link
Member Author

cmb69 commented Jul 19, 2021

If it's not a bug, there's nothing to fix for me. I have reverted the commits, and sent a mail to the RMs to not forget to revert from PHP-7.4.22 and PHP-8.0.9 as well.

carusogabriel added a commit that referenced this pull request Jul 29, 2021
This reverts commit 717f1ed, as requested by the author via
#7234 (comment).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants