ID: 50224 User updated by: christian dot lawrence at calorieking dot com Reported By: christian dot lawrence at calorieking dot com Status: Bogus Bug Type: JSON related PHP Version: 5.2SVN-2009-11-19 (snap) New Comment:
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. Previous Comments: ------------------------------------------------------------------------ [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 http://bugs.php.net/?id=50224&edit=1
