2

I"m creating a PHP script that handles JSON input (via a $_POST variable). It"s extracts data from the JSON and uploads it to an SQL database. I want the JSON in a particular format:

$object = json_decode('{
    "key_a":[{"value_a":10,"value_b":7},{"value_a":10,"value_b":7},{"value_a":10,"value_b":7}],
    "key_b":[{"value_a":10,"value_b":7}],
    "key_c":[{"value_a":10,"value_b":7},{"value_a":10,"value_b":7}]
    }',true);

Basically, an object with keys in, each of which should hold an array (no matter what size it is). I use json_decode(json,true) to convert it to an associative array (as opposed to object). I"ve had to add lots of checks in for each of the keys, checking if they"re objects or arrays (as the ASP.net page that the extract comes from converts arrays with single objects in, to objects - removing the array that holds them). The checks then convert them back to arrays, if there"s an object where I"d like an array holding an object:

if(is_object($object["key_b"]))
{
    $a = array();
    $a[] = $object["key"];
    $object["key"] = $a;
}

I then iterate through the array, adding the values to rows in an SQL database. This all works fine, but when converting back to JSON with json_encode, any keys that hold arrays with only one object in, remove the array, and leave just the object under that key:

echo(json_encode($object));
// RETURNED JSON  
'{
        "key_a":[{"value_a":10,"value_b":7},{"value_a":10,"value_b":7},{"value_a":10,"value_b":7}],
        "key_b":{"value_a":10,"value_b":7},
        "key_c":[{"value_a":10,"value_b":7},{"value_a":10,"value_b":7}]
    }'

You see, key_b no longer holds an array, but an object! This is really annoying, as I plan to create a JavaScript script that iterates through the arrays, adding one DOM element (div) for each of the objects.

Why does this happen? Is there any way to keep them as arrays, even if there"s only one object in the array?

I"ve tried:

if(is_object($object["key_b"]))
{
    $a = array();
    $a[] = array_values($object["key"]);
    $object["key"] = $a;
}

and

if(is_object($object["key_b"]))
{
    $a = array();
    $a[0] = array_values($object["key"]);
    $object["key"] = $a;
}

But it seems like nothing prevents json_encode from affecting the JSON in this way.

It"s not hard to get around this - but it means adding one check per key (checking whether it"s an array or value), which is particularly time consuming as the data extract that comes through is really big.

Any advice would be greatly appreciated.

EDIT: changed ' to " in JSON - though, this is only an example I just wrote to show the structure.

EDIT: I'm using references to cut my coding time down, if this changes anything?:

$t =& $object["key_b"];
if(is_object($t))
{
    $a = array();
    $a[] = $t;
    $t = $a;
}
Daniel Price
  • 1,132
  • 8
  • 18
  • What Javascript/JSON calls an "object" and what PHP calls an object are quite different. What exactly is `$object["key"]`? Is your code in the `if` ever being executed? – deceze Sep 05 '14 at 15:15
  • I just wrote it as an example - it's not the actual JSON I use, sorry. – Daniel Price Sep 05 '14 at 15:15
  • Hmm, good question, deceze - I'm not sure! I treated this like javascript treats objects / arrays. – Daniel Price Sep 05 '14 at 15:16
  • I edited the OP to show what I meant by object["key"]. – Daniel Price Sep 05 '14 at 15:21
  • I think you should use `is_array` instead of `is_object` as arrays are returned when a json string is decoded to an associative array. – sikhlana Sep 05 '14 at 15:23
  • Fundamentally, neither PHP nor JavaScript nor JSON has any issue with an array with a single element in it, so it's something specific to your code. `json_encode([ array( "foo" => "bar") ])` results in a string containing `[{"foo":"bar"}]`, which `JSON.parse` (JavaScript side) will correctly interpret as an array with a single entry in it. Similarly, feeding the string `[{"foo":"bar"}]` into `json_decode` correctly yields an array containing a single object. – T.J. Crowder Sep 05 '14 at 15:25
  • I have just updated OP - I'm using references (not just in this layer - which is actually the secondary layer in my JSON extract) - would this change anything? I've tested it in a smaller example which produced the results I'm looking for. I'm probably doing something wrong somewhere - it's such a large script (to handle a very large JSON extract) - I will look over my code quickly. I just thought maybe this was the normal behaviour of json_encode() if you didn't do something else. And I wish people would tell me why they decide to downvote my OP when I'm just asking for help? – Daniel Price Sep 05 '14 at 15:31

1 Answers1

0

It appears using is_object() on a key of an associative array will not return true. I just knocked up this example, to prove this:

$json = json_decode('{"job_details":{"a":[{"x":5},{"y":23},{"z":18}],"b":{"x":19},"c":[{"x":64},{"y":132}]}}',true);

echo(json_encode($json)."<br><br>");

$t =& $json["job_details"]["b"];
if(is_object($t))
{
    $a = array();
    $a[] = $t;
    $t = $a;
    echo("IS OBJECT<br><br>");
}

echo(json_encode($json));

I will find another means of checking what value is held within an associative arrays key.

I was actually trying to find whether the value in the key is an associative array or not (not an object) - I just didn't realise they were different in PHP.

I must just use this custom function:

function is_assoc($array) 
{
    return (bool)count(array_filter(array_keys($array), 'is_string'));
}

From: How to check if PHP array is associative or sequential?

Which returns true if the value is an associative array.

Community
  • 1
  • 1
Daniel Price
  • 1,132
  • 8
  • 18
  • not true. is_object tests for objects. You array value happened to NOT be one. all php arrays are dual-mode. associative+sequential. PHP doesn't care. but `$a['foo'] = new StdClass; var_dump(is_object($a['foo']))` will return true. – Marc B Sep 05 '14 at 18:46
  • Yes, but when using json_decode(), you can either use it as json_decode($string) which turns the JSON into an object, or json_decode(string,true) - which turns the JSON into an associative array. – Daniel Price Sep 06 '14 at 01:14