7

I want to pre-parse a json an convert all numbers in the json (integers or float) to strings.

For example:

{
 "integer": 10000,
 "big_integer": 100000999499498485845848584584584,
 "float1" : 1.121212,
 "float2" : 8.226347662837406e+09
}

to this:

{
 "integer": "10000",
 "big_integer": "100000999499498485845848584584584",
 "float1" : "1.121212",
 "float2" : "8226347662.837406"
}

Update I have found the following but it does not work for floats:

$jsonString = '[{"name":"john","id":5932725006},{"name":"max","id":4953467146}]';

echo preg_replace('/("\w+"):(\d+)/', '\\1:"\\2"', $jsonString);
//prints [{"name":"john","id":"5932725006"},{"name":"max","id":"4953467146"}]

Update 2 Fixed second float value. It had two points.

Community
  • 1
  • 1
Jose Celano
  • 539
  • 1
  • 7
  • 14

6 Answers6

10

Use JSON_BIGINT_AS_STRING option:

json_decode($jsonString, false, 512, JSON_BIGINT_AS_STRING)

Oleg
  • 7,070
  • 4
  • 47
  • 49
2

Use this: It should work

echo preg_replace('/\: *([0-9]+\.?[0-9e+\-]*)/', ':"\\1"', $jsonString);
  • It does not work. It returns: `{"integer""10000","big_integer""100000999499498485845848584584584","float1""1.121212","float2""8.226347662".837406e+09}` – Jose Celano May 08 '15 at 09:23
  • Sorry, it does not work but really returns this: `{"integer""10000","big_integer""100000999499498485845848584584584","float1""1.121212","float2""8.226347662837406e+09"}` with new new update2 in the question – Jose Celano May 08 '15 at 11:49
  • Thank you @jibran-bhat. It works. Although now I have another problem related to this. I want to convert hte json to an object and then get the original json but the object has to use string for json numbers. More info: http://stackoverflow.com/questions/30123862/encoding-and-decoding-floats-in-json-with-php-without-losing-precision – Jose Celano May 08 '15 at 21:57
  • Never ever use regex for jsons. For example this could corrupt json containing strings with colons and numbers. And many other potential issues. – Oleg Jun 15 '16 at 10:36
  • 1
    Why is this accepted? It fails on the scientific float: "float2" : 8.226347662837406e+09 and be aware it will also fail on lists "[1.2, 3.0]" – Grain Nov 25 '17 at 10:31
1

I like this is solution for big float:

$json = '{"data":[[0.00004639,683724.2687321],[0.00004658,190091.61007863]]}';

$json = preg_replace('/([0-9]+)\.([0-9]+)/', '"$1.$2"', $json);

print_r(json_decode($json, true));

This is code replace only float to string and you should use it before call json_decode()

JSON:

{"data":[[0.00004639,683724.2687321],[0.00004658,190091.61007863]]}

After decode:

 array (
      'data' => array (
          0 => array (
            0 => '0.00004639',
            1 => '683724.2687321',
          ),
          1 => array (
            0 => '0.00004658',
            1 => '190091.61007863',
          ),
      ),
    )
1

Here is a regex which works on float numbers, and it works for attributes, but also arrays. It also works for negative floats.

preg_replace('/((?<=":)|(?<=\[)|(?<=,))(?<!")(-?\d+\.\d+)(?!")/', '"$2"', $json)

If you also want to cover for scientific notations, this will work but this will also convert integers to strings

preg_replace('/((?<=":)|(?<=\[)|(?<=,))(?<!")(-?[\d\.]+((e|E)(\+|-)\d+)?)(?!")/', '"$2"', $json)

The inspiration was taken from this answer, i've adjusted the regex to be even able to use replace, and expanded it to work with arrays and negatives https://stackoverflow.com/a/35008486

Tested with string {"array":[[0.00004639,683724.2687321],[0.00004658,190091.61007863,190091.61007863]],"and_finally":{"negative_float":-1.123,"negative_int":-1,"first_name":"sa123mp5e-19le","last_name":"la5.1e+5stn543.123,ame","integer":"100","another_float":"1555.20","int":100,"float":1555.20,"floatAsString":"1555.20","date":"2015-01-01 15:23:51","somefloat":[14,23],"somefloat2":[5e-7,23.33],"scientific_negative_float":5.2e-7,"scientific_positive_float":5E+19}}

Issues

This will fail if there is whitespace in the json (which in production environment is never the case). If you have whitespace then you could just remove all whitespace with this (but if you have sentences anywhere in the json, this will merge it into a single long word)

preg_replace('/\s/', '', $json)

Another issue with this approach is that the array matches are not safe if they are found within a string. These will be rare, but they still might happen.

This will fail {"last_name":"lastn,543.123ame"}

This will also fail {"last_name":"lastn[543.123ame"}

Unfortunately there is no straightforward way of getting around these limitations using only one regex pass. However, if you have a response that contains purely numbers, then this works like a charm!

0

If anyone was looking for regex to match also negative numbers, here it is:

echo preg_replace('/\: *([0-9]+\.?[0-9e+\-]*|-[0-9]+\.?[0-9e+\-]*)/', ':"\\1"', $jsonString);
Ilya Shevyryaev
  • 756
  • 6
  • 8
0

Here is the most correct way to wrap such numbers in quotation marks, making them strings. This does not distort the original appearance of the json string and takes into account the scientific format. Github (composer)

$regexp = '/"(\s*)\:(\s*)(\-?\d+([eE][\+|\-]?\d+|\.\d+)+)(\s*[,(\s*)|\}])/';
$json_string = preg_replace($regexp, "$1:$2\"$3\"$5", $json);