Reputation: 77
the objective: InfoVis Demo Tree
Json specification format: InfoVis-loading and serving JSON data
I have this php array: $my_array :
Array
(
[item_1] => Array
(
[id] => item_1_ID
[name] => item_1_NAME
[data] => item_1_DATA
[children] => Array
(
[door] => Array
(
[id] => door_ID
[name] => door_NAME
[data] => door_DATA
[children] => Array
(
[mozart] => Array
(
[id] => mozart_ID
[name] => mozart_NAME
[data] => mozart_DATA
[children] => Array
(
[grass] => Array
(
[id] => grass_ID
[name] => grass_NAME
[data] => yes
)
[green] => Array
(
[id] => green_ID
[name] => green_NAME
[data] => no
)
[human] => Array
(
[id] => human_ID
[name] => human_NAME
[data] => human_DATA
[children] => Array
(
[blue] => Array
(
[id] => blue_ID
[name] => blue_NAME
[data] => blue_DATA
[children] => Array
(
[movie] => Array
(
[id] => movie_ID
[name] => movie_NAME
[data] => yes
)
)
)
)
)
)
)
)
)
[beat] => Array
(
[id] => beat_ID
[name] => beat_NAME
[data] => yes
)
[music] => Array
(
[id] => music_ID
[name] => music_NAME
[data] => no
)
)
)
)
{
"item_1": {
"id": "item_1_ID",
"name": "item_1_NAME",
"data": "item_1_DATA",
"children": {
"door": {
"id": "door_ID",
"name": "door_NAME",
"data": "door_DATA",
"children": {
"mozart": {
"id": "mozart_ID",
"name": "mozart_NAME",
"data": "mozart_DATA",
"children": {
"grass": {
"id": "grass_ID",
"name": "grass_NAME",
"data": "yes"
},
"green": {
"id": "green_ID",
"name": "green_NAME",
"data": "no"
},
"human": {
"id": "human_ID",
"name": "human_NAME",
"data": "human_DATA",
"children": {
"blue": {
"id": "blue_ID",
"name": "blue_NAME",
"data": "blue_DATA",
"children": {
"movie": {
"id": "movie_ID",
"name": "movie_NAME",
"data": "yes"
}
}
}
}
}
}
}
}
},
"beat": {
"id": "beat_ID",
"name": "beat_NAME",
"data": "yes"
},
"music": {
"id": "music_ID",
"name": "music_NAME",
"data": "no"
}
}
}
}
But to InfoVis the current json output (json_encode($my_array)) has 3 problems:
let me point the problem so maybe you can help with an function to transform this json string:
see this slice of json_encode($my_array) output:
{
"item_1": {
"id": "item_1_ID",
"name": "item_1_NAME",
"data": "item_1_DATA",
"children": {
"door": {
"id": "door_ID",
{
"item_1": {
we have to remove those keys like: "item_1":
"children": {
"door": {
"id": "door_ID",
the correct code for this should be:
"children": [
{
"id": "door_ID",......
"door": was removed... because it`s a key
"children": { => becomes" "children": [
"children": [
{
"id": "grass_ID",
"name": "grass_NAME",
"data": "yes"
},
{
"id": "green_ID",
"name": "green_NAME",
"data": "no"
}
]
json = {
id: "node02",
name: "0.2",
children: [{
id: "node13",
name: "1.3",
children: [{
id: "node24",
name: "2.4"
}, {
id: "node222",
name: "2.22"
}]
}, {
id: "node125",
name: "1.25",
children: [{
id: "node226",
name: "2.26"
}, {
id: "node237",
name: "2.37"
}, {
id: "node258",
name: "2.58"
}]
}, {
id: "node165",
name: "1.65",
children: [{
id: "node266",
name: "2.66"
}, {
id: "node283",
name: "2.83"
}, {
id: "node2104",
name: "2.104"
}, {
id: "node2109",
name: "2.109"
}, {
id: "node2125",
name: "2.125"
}]
}, {
id: "node1130",
name: "1.130",
children: [{
id: "node2131",
name: "2.131"
}, {
id: "node2138",
name: "2.138"
}]
}]
};
is it clear to understand?
Hope anyone can help me.. I'm working on this for days!
thank you.
Upvotes: 2
Views: 9878
Reputation: 16962
This is documented behaviour. An associative array will produce an object literal when JSON stringified with json_encode
. Update your original array structure to represent the outcome you want, instead of mangling the produced JSON representation, or wrap your own solution around json_encode
for each object.
Edit: attempting a cleanup operation
$original = <your original data-array>; // assumed, I reversed your encoded JSON as test data
// Start by stripping out the associative keys for level 1
$clean = array_values($original);
// Then recursively descend array, and do the same for every children-property encountered
function &recursiveChildKeysCleaner(&$arr) {
// If $arr contains 'children'...
if (array_key_exists('children', $arr)) {
/// ...strip out associative keys
$arr['children'] = array_values($arr['children']);
// ...and descend each child
foreach ($arr['children'] as &$child) {
recursiveChildKeysCleaner($child);
}
}
return $arr;
}
foreach ($clean as &$item) {
recursiveChildKeysCleaner($item);
}
unset($item);
echo json_encode($clean);
[{
"id": "item_1_ID",
"name": "item_1_NAME",
"data": "item_1_DATA",
"children": [{
"id": "door_ID",
"name": "door_NAME",
"data": "door_DATA",
"children": [{
"id": "mozart_ID",
"name": "mozart_NAME",
"data": "mozart_DATA",
"children": [{
"id": "grass_ID",
"name": "grass_NAME",
"data": "yes"
},
{
"id": "green_ID",
"name": "green_NAME",
"data": "no"
},
{
"id": "human_ID",
"name": "human_NAME",
"data": "human_DATA",
"children": [{
"id": "blue_ID",
"name": "blue_NAME",
"data": "blue_DATA",
"children": [{
"id": "movie_ID",
"name": "movie_NAME",
"data": "yes"
}]
}]
}]
}]
},
{
"id": "beat_ID",
"name": "beat_NAME",
"data": "yes"
},
{
"id": "music_ID",
"name": "music_NAME",
"data": "no"
}]
}]
Upvotes: 2
Reputation: 22247
Try this quickie conversion function
function fixit($yourArray) {
$myArray = array();
foreach ($yourArray as $itemKey => $itemObj) {
$item = array();
foreach ($itemObj as $key => $value) {
if (strtolower($key) == 'children') {
$item[$key] = fixit($value);
} else {
$item[$key] = $value;
}
}
$myArray[] = $item;
}
return $myArray;
}
$fixed = fixit($my_array);
$json = json_encode($fixed);
Upvotes: 5
Reputation: 360732
PHP doesn't differentiate between arrays (numeric keys) and associative arrays (string keys). They're all just Arrays. Javascript DOES differentiate. Since you're using string keys, they HAVE to be done as objects ({}
) in JS.
You can't tell json_encode to ignore the keys in an array (e.g. your 'children' sub-arrays). That'd mean the produced JSON is NOT the same as the original PHP structure - you've now changed key names.
You'd have to process your array and convert all those children sub-array keys to numbers:
grass -> 0
green -> 1
etc...
so that json-encode could see that it's a numerically keyed PHP array, meaning it'll produce an actual javavscript array ([]
), and not an object ({}
).
The alternative is writing your own JSON-encoder to do this on-the-fly for you.
Upvotes: 2