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", ¶meter, ¶meter_len, &assoc) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|bb", ¶meter, ¶meter_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", ¶meter, ¶meter_len, &assoc) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|bb", ¶meter, ¶meter_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