Edit report at http://bugs.php.net/bug.php?id=46363&edit=1

 ID:                 46363
 Updated by:         ahar...@php.net
 Reported by:        191919 at gmail dot com
 Summary:            json_decode lacks a 'num_as_string' feature
-Status:             Open
+Status:             Closed
 Type:               Feature/Change Request
-Package:            Feature/Change Request
+Package:            JSON related
 Operating System:   *
 PHP Version:        5.2.6
-Assigned To:        
+Assigned To:        aharvey
 Block user comment: N

 New Comment:

Trunk now has the JSON_BIGINT_AS_STRING option for json_decode() which
does just this.


Previous Comments:
------------------------------------------------------------------------
[2010-03-30 17:59:48] myfbcompany at gmail dot com

I have the same problem, but with integers.



I'm retrieving facebook information and some ids are 15 digits long, and
the json_decode function round the number to 12 digits and add 3 zeros
at the end.



It would be nice to have the numbers as string.



Thanks

------------------------------------------------------------------------
[2008-11-04 07:18:29] ka...@php.net

As a workaround you can always change the precision:



C:\php\src>php -r "var_dump(json_decode('{\"a\":
1232487234.97323948}'));"

object(stdClass)#1 (1) {

  ["a"]=>

  float(1232487234.9732)

}



C:\php\src>php -d precision=24 -r "var_dump(json_decode('{\"a\":
1232487234.9732

3948}'));"

object(stdClass)#1 (1) {

  ["a"]=>

  float(1232487234.97323942184448)

}



:), but I would still like a feature like this

------------------------------------------------------------------------
[2008-10-22 10:17:37] 191919 at gmail dot com

New patch



---



diff -u json_old/JSON_parser.c json/JSON_parser.c

--- json_old/JSON_parser.c      2007-06-14 01:56:41.000000000 +0800

+++ json/JSON_parser.c  2008-10-22 18:10:26.000000000 +0800

@@ -278,10 +278,15 @@

 }

 

 

-static void json_create_zval(zval **z, smart_str *buf, int type)

+static void json_create_zval(zval **z, smart_str *buf, int type, int
num_as_string)

 {

     ALLOC_INIT_ZVAL(*z);

 

+    if (num_as_string && (type == IS_LONG || type == IS_DOUBLE))

+    {

+        type = IS_STRING;

+    }

+

     if (type == IS_LONG)

     {

        double d = zend_strtod(buf->c, NULL);

@@ -399,7 +404,7 @@

     machine with a stack.

 */

 int

-JSON_parser(zval *z, unsigned short p[], int length, int assoc
TSRMLS_DC)

+JSON_parser(zval *z, unsigned short p[], int length, int assoc, int
num_as_string TSRMLS_DC)

 {

     int b;  /* the next character */

     int c;  /* the next character class */

@@ -501,7 +506,7 @@

                     zval *mval;

                     smart_str_0(&buf);

 

-                    json_create_zval(&mval, &buf, type);

+                    json_create_zval(&mval, &buf, type,
num_as_string);

 

                     if (!assoc)

                     {

@@ -573,7 +578,7 @@

                     zval *mval;

                     smart_str_0(&buf);

 

-                    json_create_zval(&mval, &buf, type);

+                    json_create_zval(&mval, &buf, type,
num_as_string);

                    
add_next_index_zval(JSON(the_zstack)[JSON(the_top)], mval);

                     buf.len = 0;

                     JSON_RESET_TYPE();

@@ -626,7 +631,7 @@

                      JSON(the_stack[JSON(the_top)]) == MODE_ARRAY))

                 {

                     smart_str_0(&buf);

-                    json_create_zval(&mval, &buf, type);

+                    json_create_zval(&mval, &buf, type,
num_as_string);

                 }

 

                 switch (JSON(the_stack)[JSON(the_top)]) {

diff -u json/JSON_parser.h json/JSON_parser.h

--- json_old/JSON_parser.h      2006-07-20 00:17:15.000000000 +0800

+++ json/JSON_parser.h  2008-10-22 16:32:56.000000000 +0800

@@ -3,4 +3,4 @@

 #include "php.h"

 #include "ext/standard/php_smart_str.h"

 

-extern int JSON_parser(zval *z, unsigned short p[], int length, int
assoc TSRMLS_DC);

+extern int JSON_parser(zval *z, unsigned short p[], int length, int
assoc, int num_as_string TSRMLS_DC);

diff -u json/json.c json/json.c

--- json_old/json.c     2007-12-31 15:20:07.000000000 +0800

+++ json/json.c 2008-10-22 16:33:53.000000000 +0800

@@ -411,10 +411,11 @@

     char *parameter;

     int parameter_len, utf16_len;

     zend_bool assoc = 0; /* return JS objects as PHP objects by default
*/

+    zend_bool num_as_string = 0; /* don't decode integers and doubles
as strings */

     zval *z;

     unsigned short *utf16;

 

-    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b",
&parameter, &parameter_len, &assoc) == FAILURE) {

+    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|bb",
&parameter, &parameter_len, &assoc, &num_as_string) == FAILURE) {

         return;

     }

 

@@ -437,7 +438,7 @@

     }

 

     ALLOC_INIT_ZVAL(z);

-    if (JSON_parser(z, utf16, utf16_len, assoc TSRMLS_CC))

+    if (JSON_parser(z, utf16, utf16_len, assoc, num_as_string
TSRMLS_CC))

     {

         *return_value = *z;

------------------------------------------------------------------------
[2008-10-22 08:57:16] 191919 at gmail dot com

Description:
------------
json_decode lacks a 'num_as_string' feature. I made a patch which adds a
third optional 'num_as_string' parameter to json_decode to force it to
decode all numbers as strings.



diff -u json_orig/JSON_parser.c json/JSON_parser.c

--- json_orig/JSON_parser.c     2007-06-14 01:56:41.000000000 +0800

+++ json/JSON_parser.c  2008-10-22 16:33:32.000000000 +0800

@@ -278,10 +278,15 @@

 }

 

 

-static void json_create_zval(zval **z, smart_str *buf, int type)

+static void json_create_zval(zval **z, smart_str *buf, int type, int
num_as_string)

 {

     ALLOC_INIT_ZVAL(*z);

 

+    if (num_as_string)

+    {

+        type = IS_STRING;

+    }

+

     if (type == IS_LONG)

     {

        double d = zend_strtod(buf->c, NULL);

@@ -399,7 +404,7 @@

     machine with a stack.

 */

 int

-JSON_parser(zval *z, unsigned short p[], int length, int assoc
TSRMLS_DC)

+JSON_parser(zval *z, unsigned short p[], int length, int assoc, int
num_as_string TSRMLS_DC)

 {

     int b;  /* the next character */

     int c;  /* the next character class */

@@ -501,7 +506,7 @@

                     zval *mval;

                     smart_str_0(&buf);

 

-                    json_create_zval(&mval, &buf, type);

+                    json_create_zval(&mval, &buf, type,
num_as_string);

 

                     if (!assoc)

                     {

@@ -573,7 +578,7 @@

                     zval *mval;

                     smart_str_0(&buf);

 

-                    json_create_zval(&mval, &buf, type);

+                    json_create_zval(&mval, &buf, type,
num_as_string);

                    
add_next_index_zval(JSON(the_zstack)[JSON(the_top)], mval);

                     buf.len = 0;

                     JSON_RESET_TYPE();

@@ -626,7 +631,7 @@

                      JSON(the_stack[JSON(the_top)]) == MODE_ARRAY))

                 {

                     smart_str_0(&buf);

-                    json_create_zval(&mval, &buf, type);

+                    json_create_zval(&mval, &buf, type,
num_as_string);

                 }

 

                 switch (JSON(the_stack)[JSON(the_top)]) {

diff -u json/JSON_parser.h json/JSON_parser.h

--- json_orig/JSON_parser.h     2006-07-20 00:17:15.000000000 +0800

+++ json/JSON_parser.h  2008-10-22 16:32:56.000000000 +0800

@@ -3,4 +3,4 @@

 #include "php.h"

 #include "ext/standard/php_smart_str.h"

 

-extern int JSON_parser(zval *z, unsigned short p[], int length, int
assoc TSRMLS_DC);

+extern int JSON_parser(zval *z, unsigned short p[], int length, int
assoc, int num_as_string TSRMLS_DC);

diff -u json/json.c json/json.c

--- json_orig/json.c    2007-12-31 15:20:07.000000000 +0800

+++ json/json.c 2008-10-22 16:33:53.000000000 +0800

@@ -411,10 +411,11 @@

     char *parameter;

     int parameter_len, utf16_len;

     zend_bool assoc = 0; /* return JS objects as PHP objects by default
*/

+    zend_bool num_as_string = 0; /* don't decode integers and doubles
as strings */

     zval *z;

     unsigned short *utf16;

 

-    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b",
&parameter, &parameter_len, &assoc) == FAILURE) {

+    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|bb",
&parameter, &parameter_len, &assoc, &num_as_string) == FAILURE) {

         return;

     }

 

@@ -437,7 +438,7 @@

     }

 

     ALLOC_INIT_ZVAL(z);

-    if (JSON_parser(z, utf16, utf16_len, assoc TSRMLS_CC))

+    if (JSON_parser(z, utf16, utf16_len, assoc, num_as_string
TSRMLS_CC))

     {

         *return_value = *z;











Reproduce code:
---------------
<?

$json = '{"a":1232487234.97323948}';

var_dump(json_decode($json, true));

?>



Expected result:
----------------
array(1) {

  ["a"]=>

  string(19) "1232487234.97323948"

}



Actual result:
--------------
array(1) {

  ["a"]=>

  float(1232487234.9732)

}




------------------------------------------------------------------------



-- 
Edit this bug report at http://bugs.php.net/bug.php?id=46363&edit=1

Reply via email to