Edit report at https://bugs.php.net/bug.php?id=50224&edit=1
ID: 50224
Comment by: josh dot adell at gmail dot com
Reported by: christian dot lawrence at calorieking dot com
Summary: json_encode() does not always encode a float as a
float
Status: Not a bug
Type: Bug
Package: JSON related
PHP Version: 5.2SVN-2009-11-19 (snap)
Block user comment: N
Private report: N
New Comment:
This is still an issue, specifically when JSON encoding for talking to APIs
that
don't allow mixed type arrays.
For instance, json_encode(array(1.2, 2.3)) properly encodes to "[1.2, 2.3]"
But, json_encode(array(1.0, 2.3)) encodes to "[1, 2.3]" which fails if the
receiving end does not allow mixed-type arrays.
Any chance on this ever being fixed?
PHP Version: 5.3.10
Previous Comments:
------------------------------------------------------------------------
[2009-11-20 10:39:53] christian dot lawrence at calorieking dot com
And there lines the problem - there is no way to express the fractional part if
json_encode() does not even deal with it in the first place.
An integer and an integer represented as a floating point number are not the
same thing because they have different types, as follows:
<?php
$a = 12;
var_dump($a); //int(12)
$b = 12.0; // This has a fractional part, hence it is a floating
point number and not an integer
var_dump($b); //float(12)
var_dump($a === $b); //bool(false)
?>
Numerically they have the same value, but we all know this to be true:
<?php
var_dump($a == $b); //bool(true)
?>
There is always a fractional part of any integer when it is represented as a
floating point number. It is implied and can, simply, be expressed by
appending a ".0" to the integer part. There is nothing in the JSON encoding
rules on http://www.json.org/ which disallows this (see "int frac" form for
specifics).
Decoding a valid and legitimate encoding of an integer when it is represented
as a floating point number gives the correct PHP floating point type:
<?php
var_dump(json_decode("12.0")); //float(12)
?>
Decoding an integer-encoded stream also gives the correct PHP integer type:
<?php
var_dump(json_decode("12")); //int(12)
?>
I fail to see how my bug report is bogus when json_encode() is unable to
produce a perfectly valid and legitimate encoding yet json_decode() is capable
of doing the right thing.
Surely, the json_encode() implementation must be identifying the data type
being encoded, presumably it is using equivalents for is_object() and
is_array(). Why not use equivalents for is_int() or is_float() as well?
A reliable data interchange format should not purport to do any type-casting
from the primitive types it was provided for encoding. ie: If you encode a
float then you should expect to decode a float. As far as I am concerned
json_encode() is un-reliable and fails to encode my float, which I have
confirmed in my results.
I humbly ask that you reconsider your position.
------------------------------------------------------------------------
[2009-11-19 15:12:56] [email protected]
Yes, IF you were passing fractional part. But you're not. See the output of
var_dump($f) in your results..
------------------------------------------------------------------------
[2009-11-19 09:14:05] christian dot lawrence at calorieking dot com
Take a look at the format for "number" at http://www.json.org/ and observe the
form for a "int frac". This clearly indicates that there is support for
representing a floating point number, even integer floats.
The json_encode() function clearly supports encoding of floating point numbers.
json_decode() is capable of deserialising "12.0" as a integer floating point
number.
If you encode a floating point number, then one should expect to decode a
floating point number.
If json_encode()/json_decode() is to be used as a serious and reliable data
exchange format, then there should be no loss or conversion of primitive type
information.
Please re-consider.
------------------------------------------------------------------------
[2009-11-19 08:51:56] [email protected]
There's is just "number" type in JSON for numbers. And as such, this is working
just like it should and PHP tries it's best at guessing what type the numbers
might be.
------------------------------------------------------------------------
[2009-11-19 05:45:10] christian dot lawrence at calorieking dot com
Description:
------------
json_encode()-ing an integer when it is represented as floating point number
results in a change of type when json_decode() decodes the output.
Examples of such floating point numbers are: -123.0, -1.0, 0.0, 1.0, 123.0
Reproduce code:
---------------
<?php
function jsonRoundTrip($f) {
$e = json_encode($f);
$d = json_decode($e);
var_dump($f, $e, $d);
echo "\n";
}
jsonRoundTrip(12.3); // This is a float
jsonRoundTrip(12); // This is an integer
jsonRoundTrip(12.0); // This is an integer represented as a float
jsonRoundTrip(0.0); // This is an integer represented as a float
?>
Expected result:
----------------
float(12.3)
string(4) "12.3"
float(12.3)
int(12)
string(2) "12"
int(12)
float(12)
string(4) "12.0"
float(12)
float(0)
string(3) "0.0"
float(0)
Actual result:
--------------
float(12.3)
string(4) "12.3"
float(12.3)
int(12)
string(2) "12"
int(12)
float(12)
string(2) "12"
int(12)
float(0)
string(1) "0"
int(0)
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=50224&edit=1