1

I have a PHP script that outputs JSON data which is parsed by Javascript in Browsers, and also by iPhone and Android apps.

Previously, I found that when PHP converted array data into a JSON, it would make all numberical values into strings as indicated by double quotes. So, for example, "id" : 1 would become "id" : "1". This seemed to confuse some of the Javascript functions that received the JSON data, so I ran this regular expression on the JSON in PHP in order to make sure numbers weren't made into strings:

$JSONOutput = preg_replace('/"(-?\d+\.?\d*)"/', '$1', json_encode($JSONOutput));

However, this also has the effect of removing double quotes from both keys and values, so 1 : "first value" becomes "1" : "first value". It turns out this is a problem because if JSON keys aren't strings, then the iPhone app that recieves the data complains.

So, what I want to do is make sure all values in the JSON are preserved as integers, but all keys are made into strings. Is there a way I can run the regular expression I have above on just the values? Or any other process that would give me a similar result?

Questioner
  • 7,133
  • 16
  • 61
  • 94
  • 2
    I don't get it. Keys of JSON objects are **always** strings. Your question is confusing. Can you show one concrete example of an array and how it is encoded and what you want to change about it? – deceze Jan 06 '13 at 07:28
  • 1
    Don't transform the *output* of `json_encode`, modify the *input* you send into it. Use `array_walk_recursive` to walk over all values and convert them with `is_numeric($value) ? floatval($value) : $value` or something similar. – DCoder Jan 06 '13 at 07:31
  • @DCoder: That sounds like a good way to go. Can you provide a verbose example in an answer? – Questioner Jan 06 '13 at 07:56
  • I think TJCrowder's answer explains the issue very well. (Also, my suggestion is rather heavy-handed. Converting the data into the right datatype should not be just "if it walks like a number and quacks like a number, cast it to number", it should be done with domain knowledge of which fields are numbers and which are not.) – DCoder Jan 06 '13 at 08:16
  • @DCoder et al, through exploring this issue, I realized that my root issue is the way I am getting values from MySQL. I have opened [another question](http://stackoverflow.com/q/14180981/184108) to address that. – Questioner Jan 06 '13 at 09:51

1 Answers1

2

Is there a way I can run the regular expression I have above on just the values?

You're much better off avoiding post-processing the string.

Previously, I found that when PHP converted array data into a JSON, it would make all numberical values into strings as indicated by double quotes. So, for example, "id" : 1 would become "id" : "1".

The answer here is to make sure that the number values really are numbers. If you're seeing strings with digits in them where you expect numbers, it's because the value in the PHP object/array is not a number. That's what you need to fix.

For example, this code:

<?php
    header('Content-Type: application/json');
    $x = array(
        "number" => 1,
        "string" => "2"
        );
    echo json_encode($x);
?>

...quite correctly produces this output:

{"number":1,"string":"2"}

Note how the value that's really a number in the PHP code comes out as a number in the JSON.

So rather than post-processing the string, the answer is to correct the data you're feeding into json_encode.


Replying to your comment below:

I understand that I could specifically assign string names to keys, but the array in question is generated automatically with a while loop that keeps appending numbers, and those numbers are used in counting operations, so I don't think this would work in my case.

It doesn't make the slightest difference. For example, this code:

<?php
    header('Content-Type: application/json');
    $x = array();
    for ($n = 1; $n < 5; ++$n) {
       $x["entry" . $n] = $n;
    }
    echo json_encode($x);
?>

produces this output:

{"entry1":1,"entry2":2,"entry3":3,"entry4":4}

Again note that the numbers are numbers in the input, and therefore numbers in the output.

Also note that PHP correctly handles it if the keys of the object are numbers:

<?php
    header('Content-Type: application/json');
    $x = array();
    $x["foo"] = "bar";
    for ($n = 1; $n < 5; ++$n) {
       $x[$n] = $n * 2;
    }
    echo json_encode($x);
?>

produces

{"foo":"bar","1":2,"2":4,"3":6,"4":8}
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Thank you for answering. I understand that I could specifically assign string names to keys, but the array in question is generated automatically with a while loop that keeps appending numbers, and those numbers are used in counting operations, so I don't think this would work in my case. – Questioner Jan 06 '13 at 07:57
  • @DaveMG: It doesn't make any difference, numbers are numbers. I've given a second example above. – T.J. Crowder Jan 06 '13 at 08:01