Reputation: 906
I have 2 DB tables. table 2 is relational to table 1.
In php I am building a multidimensional array to hold the data key/values.
because PHP needs to have unique "keys" MY JSON is looking like this:
[
{
"packs": {
"9": {
"characters": {
"40": {
"id": "40",
"title": "Jack Bauer",
"pic": "68bcbe014c.jpg",
"gender": "Male"
},
"41": {
"id": "41",
"title": "Chloe O'Brian",
"pic": "ffb6acc8e3.jpg",
"gender": "Male"
},
"42": {
"id": "42",
"title": "Tony Almeida",
"pic": "23f199e223.jpg",
"gender": "Male"
}
}
},
"7": {
"characters": {
"7": {
"id": "7",
"title": "Elvis Presley",
"pic": "78300767ad.jpg",
"gender": "Male"
},
"16": {
"id": "16",
"title": "Madonna",
"pic": "70663a42f7.jpg",
"gender": "Male"
},
"17": {
"id": "17",
"title": "Lady Gaga",
"pic": "c5099c619b.jpg",
"gender": "Male"
},
"21": {
"id": "21",
"title": "Pink Floyd",
"pic": "52ddce314a.jpg",
"gender": "Male"
},
"22": {
"id": "22",
"title": "Led Zeppelin",
"pic": "84cd58ada3.jpg",
"gender": "Male"
},
"31": {
"id": "31",
"title": "The Beatles",
"pic": "bd22a4d648.jpg",
"gender": "Male"
},
"32": {
"id": "32",
"title": "Foo Fighters",
"pic": "250fb6ecec.jpg",
"gender": "Male"
},
"33": {
"id": "33",
"title": "Bananarama",
"pic": "da7c2b56cf.jpg",
"gender": "Male"
},
"35": {
"id": "35",
"title": "Boney-M",
"pic": "3cbdada38b.jpg",
"gender": "Male"
},
"38": {
"id": "38",
"title": "The Spice Girls",
"pic": "4751f0fbb7.jpeg",
"gender": "Male"
},
"39": {
"id": "39",
"title": "Girls Aloud",
"pic": "644dcf71ca.jpg",
"gender": "Male"
}
}
},
"8": {
"characters": {
"9": {
"id": "9",
"title": "Keith Lemon",
"pic": "ff6ef10853.jpg.jpg",
"gender": "Male"
},
"23": {
"id": "23",
"title": "Fearne Cotton",
"pic": "0d038b6516.jpg",
"gender": "Male"
},
"24": {
"id": "24",
"title": "Holly Willoughby",
"pic": "836fc4184c.jpg",
"gender": "Male"
},
"30": {
"id": "30",
"title": "Rufus Hound",
"pic": "062bee9602.jpg",
"gender": "Male"
}
}
},
"3": {
"characters": {
"5": {
"id": "5",
"title": "Tom Cruise",
"pic": "ff296fafb9.jpg",
"gender": "Male"
},
"10": {
"id": "10",
"title": "Linda Lovelace",
"pic": "ac1bea43d3.jpg",
"gender": "Male"
},
"15": {
"id": "15",
"title": "Gwyneth Paltrow",
"pic": "43a22d7240.jpg",
"gender": "Male"
},
"44": {
"id": "44",
"title": "Errol Flynn",
"pic": "cea17c1275.jpg",
"gender": "Male"
},
"45": {
"id": "45",
"title": "Halle Berry",
"pic": "752b5c92c5.jpg",
"gender": "Male"
}
}
},
"2": {
"characters": {
"4": {
"id": "4",
"title": "Donald Duck",
"pic": "8d367f41b1.jpg",
"gender": "Male"
},
"6": {
"id": "6",
"title": "Mickey Mouse",
"pic": "8d9629c115.jpg",
"gender": "Male"
},
"28": {
"id": "28",
"title": "Pluto",
"pic": "fb2c0e2dd0.jpg",
"gender": "Male"
},
"29": {
"id": "29",
"title": "Minnie Mouse",
"pic": "378760ff77.jpg",
"gender": "Male"
},
"36": {
"id": "36",
"title": "Cinderella",
"pic": "a7e4888213.jpg",
"gender": "Male"
},
"37": {
"id": "37",
"title": "Snow White",
"pic": "a9cf05a857.jpg",
"gender": "Male"
}
}
},
"4": {
"characters": {
"3": {
"id": "3",
"title": "Bill Clinton",
"pic": "03c6567ddb.jpg",
"gender": "Male"
},
"11": {
"id": "11",
"title": "Margaret Thatcher",
"pic": "91c9fa9fd0.jpg",
"gender": "Male"
},
"13": {
"id": "13",
"title": "David Cameron",
"pic": "a689984360.jpg",
"gender": "Male"
},
"14": {
"id": "14",
"title": "Nick Clegg",
"pic": "3243e298e5.jpg",
"gender": "Male"
},
"26": {
"id": "26",
"title": "George Bush JR",
"pic": "46296f6b0e.jpg",
"gender": "Male"
},
"27": {
"id": "27",
"title": "Ed Milliband",
"pic": "66f1449994.jpg",
"gender": "Male"
}
}
},
"5": {
"characters": {
"8": {
"id": "8",
"title": "Stephen Hawking",
"pic": "b8c4f17530.jpg",
"gender": "Male"
},
"18": {
"id": "18",
"title": "Alan Turing",
"pic": "82b4d84e35.jpg",
"gender": "Male"
},
"19": {
"id": "19",
"title": "Albert Einstein",
"pic": "a6cd74dbaa.jpg",
"gender": "Male"
},
"34": {
"id": "34",
"title": "Brian Cox (prof)",
"pic": "92b6005de9.jpg",
"gender": "Male"
},
"43": {
"id": "43",
"title": "Richard Feynman",
"pic": "5de10d1128.jpg",
"gender": "Male"
}
}
},
"6": {
"characters": {
"12": {
"id": "12",
"title": "Jeff Koons",
"pic": "8e3ca5f497.jpg",
"gender": "Male"
},
"20": {
"id": "20",
"title": "Salvador Dali",
"pic": "b5bafb7934.jpg",
"gender": "Male"
},
"25": {
"id": "25",
"title": "Rembrandt",
"pic": "73e2710029.jpg",
"gender": "Male"
},
"49": {
"id": "49",
"title": "Vincent Van Gough",
"pic": "6ee455ab28.jpg",
"gender": "Male"
}
}
}
}
}
]
I am trying to solve a problem that my iOS dev wants sorting... apparently the "{"packs":{"9": " 9 is wrong and does not follow the key:value JSON structure. How on earth do I create a correct PHP array or object for that matter with the unique identifier for each of the result sets from DB table 1?
the result should be structured like this:
data_db_1:1
data_db_2:id data_db_2:title data_db_2:pic data_db_2:gender
data_db_1:2
data_db_2:id data_db_2:title data_db_2:pic data_db_2:gender
data_db_1:3
data_db_2:id data_db_2:title data_db_2:pic data_db_2:gender
data_db_1:4 data_db_2:id data_db_2:title data_db_2:pic data_db_2:gender
and look like this:
{
"id": "9",
"title": "24",
"credits": "100",
"character": [
{
"id": "50",
"title": "Jack Bauer",
"pic": "68bcbe014c.jpg",
"gender": "Male"
},
{
"id": "50",
"title": "Jack Bauer",
"pic": "68bcbe014c.jpg",
"gender": "Male"
},
{
"id": "50",
"title": "Jack Bauer",
"pic": "68bcbe014c.jpg",
"gender": "Male"
},
{
"id": "50",
"title": "Jack Bauer",
"pic": "68bcbe014c.jpg",
"gender": "Male"
}
]
}
I cant find allot on the web relating to this. The only way I can think to solve it is to create each part seperately from PHP arrays using json_encode() and echo and a mess of concat. Surely json_encode() should be capable of creating correct JSON from a simple php array, a complex php multidimensional array or a PHP object without breaking a sweat???
my php function to do this as requested:
$data_ar = output_pack_data($pack_id);
echo "[".json_encode($data_ar)."]"; // first bit of dirty here
function output_pack_data($pack_id = false)
{
global $db;
$output_keys = true; //false;
if($pack_id != false)
{
$q = "WHERE id='{$pack_id}' AND active = '1'"; // select the relevant pack ID
}
else
{
$q = "WHERE active='1' ORDER BY order_num ASC"; // select all pack ids
}
$rs = $db->rs("whoami_packs",$q);
$pack_obj = new stdClass(); // declare new std class object here......
$data = array(); // prep new array to hold the data
while($rs && $r = $db->fetch($rs)) // loop thorugh each pack id
{
$pack_obj->packs->id = $r->id; // add the pack title
$pack_obj->packs->title = $r->title; // add the pack title
$pack_obj->packs->credits = $r->credits; // add the required credits to access
$packs_rs = $db->rs("whoami_characters","WHERE pack_id='{$r->id}' AND active = '1'"); // get the character data relevant for this pack
$i=0;
while($packs_rs && $pack_r = $db->fetch($packs_rs)) // loop through the character data
{
$id = $r->id;
if($output_keys == false)
{
$data['packs'][$r->id]['characters'][$pack_r->id][$pack_r->title][$pack_r->pic][$pack_r->gender] = true; // build the array
}
else
{
$data['packs'][$r->id]['characters'][$pack_r->id]['id'] = $pack_r->id; // build the array
$data['packs'][$r->id]['characters'][$pack_r->id]['title'] = str_out($pack_r->title); // build the array
$data['packs'][$r->id]['characters'][$pack_r->id]['pic'] = $pack_r->pic;
$data['packs'][$r->id]['characters'][$pack_r->id]['gender'] = ($pack_r->gender = 'm') ? "Male" : "Female";
}
}
}
return $data; // return the array
}
Upvotes: 1
Views: 2047
Reputation: 379
Using the option JSON_FORCE_OBJECT
(Available since PHP 5.3.0, see here) will force json_encode
to create a valid JSON Object
Upvotes: 0
Reputation: 906
So it seems that json_encode() will ignore the key values if they are a simple incrementing counter....
this function:
function output_pack_data($pack_id = false)
{
global $db;
$output_keys = true; //false;
if($pack_id != false)
{
$q = "WHERE id='{$pack_id}' AND active = '1'"; // select the relevant pack ID
}
else
{
$q = "WHERE active='1' ORDER BY order_num ASC"; // select all pack ids
}
$rs = $db->rs("whoami_packs",$q);
$data = array(); // prep new array to hold the data
$i = 0; // AHA!
while($rs && $r = $db->fetch($rs)) // loop through each pack id
{
$data[$i]['pack_id'] = $r->id;
$data[$i]['title'] = $r->title; // add the pack title
$data[$i]['credits'] = $r->credits; // add the required credits to access
$chars_rs = $db->rs("whoami_characters","WHERE pack_id='{$r->id}' AND active = '1'"); // get the character data relevant for this pack
$ii = 0; // AHA!
while($chars_rs && $char_r = $db->fetch($chars_rs)) // loop through the character data
{
if($output_keys == false)
{
$data[$i]['characters'][$ii][$char_r->title][$char_r->pic][$char_r->gender] = true; // build the array
}
else
{
$data[(int)$i]['characters'][(int)$ii]['id'] = str_out($char_r->id); // build the array
$data[(int)$i]['characters'][(int)$ii]['title'] = str_out($char_r->title); // build the array
$data[(int)$i]['characters'][(int)$ii]['pic'] = $char_r->pic;
$data[(int)$i]['characters'][(int)$ii]['gender'] = ($char_r->gender = 'm') ? "Male" : "Female";
}
$ii++;
}
$i++;
}
return $data; // return the array
}
will return the desired result. Odd that and no mention of it in the documentation! oh well, sorted for now! Hope this helps anyone else with this problem.... note the use of (int) to make sure the $i or $ii counters are correct integers. Using the DB IDs in this case will not work and they will get added to the output.
Upvotes: 0
Reputation: 96159
There's some superfluous code in the function. And when you have non-consecutive (numerical) indices json_encode will not use an [x,y,z] encoding but an object notation.
Apparently your colleague wants the IDs as properties of each object not as the key to an object. Therefore just drop referencing the array element via its id but first create the complete array then append it to its parent via $parent[]. This way you get an array with sequential numeric ids -> json_encode() creates an array notation.
(untested, i'm too lazy to build sql test data from the json output provided in the original question)
function output_pack_data($pack_id=false)
{
global $db;
$data = array();
if($pack_id != false) {
$q = "WHERE id='{$pack_id}' AND active = '1'";
}
else {
$q = "WHERE active='1' ORDER BY order_num ASC";
}
$rs_packs = $db->rs("whoami_packs", $q);
while($rs_packs && ($rec_pack=$db->fetch($rs_packs)) ) {
$pack = array(
'id'=>$rec_pack->id,
'title'=>$rec_pack->title,
'credits'=>$rec_pack->credits,
'characters'=>array()
);
$rs_chars = $db->rs("whoami_characters","WHERE pack_id='{$pack->id}' AND active = '1'");
while($rs_chars && ($rec_char=$db->fetch($rs_chars)) ) {
$pack['characters'][] = array(
'id' => $rec_char->id,
'title' => str_out($rec_char->title),
'pic' => $rec_char->pic,
'gender' => 'm'==$rec_char->gender ? "Male" : "Female"
);
}
$data[] = $pack;
}
return $data;
}
And please have a read of https://en.wikipedia.org/wiki/Join_%28SQL%29 and http://www.w3schools.com/sql/sql_join.asp
Upvotes: 1
Reputation: 401
Sorry, this is a comment and not an answer (again).
I think what the iOS developer (such as myself) is saying is that you are using the id of each object to define each object, and not a key.
Your example and your developer's expected output are both correct, however it's the actual structure of the information that's the issue.
If you head over to http://json.org/example.html to see some examples of JSON data structuring it might be made a little clearer.
Let's look at this in XML. If you convert the following JSON into XML:
[
{
"1": {
"id": "1",
"title": "Jack Bauer",
"pic": "68bcbe014c.jpg",
"gender": "Male"
}
},
{
"2": {
"id": "2",
"title": "Jack Bauer",
"pic": "68bcbe014c.jpg",
"gender": "Male"
}
}
]
You will be left with:
<?xml version="1.0" encoding="UTF-8" ?>
<1>
<id>1</id>
<title>Jack Bauer</title>
<pic>68bcbe014c.jpg</pic>
<gender>Male</gender>
</1>
<2>
<id>2</id>
<title>Jack Bauer</title>
<pic>68bcbe014c.jpg</pic>
<gender>Male</gender>
</2>
</xml>
Simply put, although it is correctly structured in both cases, the data placement is not correct. the <1> and <2> nodes should be the same key, this principle follows most standards (such as RSS).
Looking at your developer's requirements, he wants (in JSON and XML examples):
{
"character": [
{
"id": "1",
"title": "Jack Bauer",
"pic": "68bcbe014c.jpg",
"gender": "Male"
},
{
"id": "2",
"title": "Jack Bauer",
"pic": "68bcbe014c.jpg",
"gender": "Male"
}
]
}
and as XML:
<?xml version="1.0" encoding="UTF-8" ?>
<character>
<id>1</id>
<title>Jack Bauer</title>
<pic>68bcbe014c.jpg</pic>
<gender>Male</gender>
</character>
<character>
<id>2</id>
<title>Jack Bauer</title>
<pic>68bcbe014c.jpg</pic>
<gender>Male</gender>
</character>
</xml>
The second examples are clearly structured more efficiently, since the key (character) defines each value, and not the id of each value itself.
Upvotes: 0