Encode nested JSON array in php - php

I want to send nested JSON array.Which contain following format.
${"posts":[{
"abc":"123",
"xyz":"123",
"pro":[{
"name":"Brinjal",
"qty":"500 gms"
},
{
"name":"Brinjal",
"qty":"500 gms"
}]
}]
}
Here is my php code:
$rows = $stmt->fetchAll();
if ($rows) {
$order["posts"] = array();
foreach ($rows as $row) {
$post = array();
$post["order_id"] = $row["order_id"];
$post["order_totalamount"] = $row["order_totalamount"];
$post["address"] = $row["address"];
$post["pincode"] = $row["pincode"];
$post["delivery_timeslot"] = $row["delivery_timeslot"];
$post["order_date"] = $row["order_date"];
$query1= "query";
$rows1 = $stmt->fetchAll();
if ($rows1) {
foreach ($rows1 as $row1) {
$query2= "query";
$rows2 = $stmt->fetchAll();
$post["product"] = array();
if ($rows2) {
$products = array();
foreach ($rows2 as $row2) {
$products["product_name"]=$row2["product_name"];
$products["prod_qty"] = $row2["product_minquantity"];
}
array_push($post["product"],$products);
echo json_encode($products);
}
}
}
array_push($order["posts"], $post);
}
echo json_encode($order);
}
From above code I got result:
$ {"posts":
[{
"order_id":"18",
"order_totalamount":"40",
"address":"2, Chetan Society, Vadodara",
"pincode":"390023",
"delivery_timeslot":"Zone wise delivery",
"order_date":"2016-03-18 17:50:53",
"product":[{"product_name":"Brinjal","prod_qty":"500 gms"}]
}]
}
But my actual product array is:
${"product_name":"Banana","prod_qty":"1 Kg"}{"product_name":"Brinjal","prod_qty":"500 gms"}
Kindly help out. I am stuck on it. tried a lot but did not get success.

In
foreach ($rows2 as $row2) {
$products["product_name"]=$row2["product_name"];
$products["prod_qty"] = $row2["product_minquantity"];
}
You overwrite $products["product_name"]and $products["prod_qty"] with the values of the last $row2.
The line {"product_name":"Banana","prod_qty":"1 Kg"}{"product_name":"Brinjal","prod_qty":"500 gms"} actually consists of two echo's:
{"product_name":"Banana","prod_qty":"1 Kg"}
{"product_name":"Brinjal","prod_qty":"500 gms"}
But you don't see the difference. I suggest echoing a string in-between them or use something like var_dump() to see how many values you're echoing.
You should do something like:
for ($i = 0; $i < count($rows2); $i++) {
$products[$i]["product_name"]=$rows2[$i]["product_name"];
$products[$i]["prod_qty"] = $rows2[$i]["product_minquantity"];
}
This will result in: [{"product_name":"Banana","prod_qty":"1 Kg"},{"product_name":"Brinjal","prod_qty":"500 gms"}]
FYI $array[] = has the same rsults as array_push(), but had less overhead of calling array_push().
EDIT:
Below a complete example since it doesn't seem to workout for you:
//Demo $order
$order = array (
'posts' =>
array (
0 =>
array (
'order_id' => '18',
'order_totalamount' => '40',
'address' => '2, Chetan Society, Vadodara',
'pincode' => '390023',
'delivery_timeslot' => 'Zone wise delivery',
'order_date' => '2016-03-18 17:50:53',
),
),
);
//Demo $rows2
$rows2 = array(
array(
'product_name' => 'banana',
'product_minquantity' => '1 Kg'
),
array(
'product_name' => 'Brinjal',
'product_minquantity' => '500 gms'
)
);
$post['product'] = array();
if ($rows2) {
$products = array();
for ($i = 0; $i < count($rows2); $i++) {
$products[$i]['product_name'] = $rows2[$i]['product_name'];
$products[$i]['prod_qty'] = $rows2[$i]['product_minquantity'];
}
$post['product'] = $products;
echo json_encode($products); //[{"product_name":"banana","prod_qty":"1 Kg"},{"product_name":"Brinjal","prod_qty":"500 gms"}]
}
//$order['posts'][] = $post;
$order['posts'][0] = $order['posts'][0] + $post;
//In this example I only have 1 item in $order['posts'] so I know to add to key 0.
//In your case you need to know which key of $rows1 you need to do the adding.
//Change the foreach loop of $rows to a for loop as well so you can define your own keynames ($i).
echo '<br>==================================================================<br>';
echo json_encode($order);
/*
{
"posts":[
{
"order_id":"18",
"order_totalamount":"40",
"address":"2, Chetan Society, Vadodara",
"pincode":"390023",
"delivery_timeslot":"Zone wise delivery",
"order_date":"2016-03-18 17:50:53",
"product":[
{
"product_name":"banana",
"prod_qty":"1 Kg"
},
{
"product_name":"Brinjal",
"prod_qty":"500 gms"
}
]
}
]
}
*/

Related

Reordering and grouping existing array

I have a JSON array as formatted below, generated in PHP using a foreach loop to generate an array from an WP ACF group (see below). I seem to be unable to use GROUP BY when getting the particular fields for this ACF group, hence the double entry for name (with different times) as shown.
[
{"name":"Location1","gigs":
{"start":"16:30","end":"21:15","title":"TestTitle1","class":"fri"}
},
{"name":"Location 2","gigs":
{"start":"15:00","end":"19:00","title":"TestTitle2","class":"fri"}
},
{"name":"Location 1","gigs":
{"start":"21:00","end":"22:00","title":"TestTitle3","class":"fri"}
}
]
This JSON array should ideally be formatted as follows, the difference being the entries with the same name/location should be combined as shown below.
[
{
"name":"Location1",
"gigs": [
{"start":"16:30","end":"21:15","title":"TestTitle1","class":"fri"},
{"start":"21:00","end":"22:00","title":"TestTitle3","class":"fri"}
]
},
{
"name":"Location 2",
"gigs": [
{"start":"15:00","end":"19:00","title":"TestTitle2","class":"fri"}
]
}
]
I've tried several array merge/combine/sort/etc functions available in PHP, but can't get it to output as intended.
Here's the code generating the array/JSON output:
function get_shows( WP_REST_Request $request ) {
$parameters = $request->get_params();
switch($parameters[1]) {
case 'fri':
$show_day = 'fri';
$show_select_day = '20170901';
break;
case 'sat':
$show_day = 'sat';
$show_select_day = '20170902';
break;
case 'sun':
$show_day = 'sun';
$show_select_day = '20170903';
break;
}
$showDates = array();
$args = array(
'posts_per_page' => -1,
'post_type' => 'performances',
'meta_key' => 'per_date',
'meta_value' => $show_select_day
);
$shows = get_posts( $args );
if ( ! empty( $shows ) ) {
$i = 0;
foreach( $shows as $show ) {
$acf = get_fields($show->ID);
$show_loc = get_the_title(get_field('per_location',$show->ID));
$show_title = get_the_title(get_field('per_busker',$show->ID));
if ( ! empty( $acf ) ) {
$showDates[$i]['name'] = $show_loc;
$showDates[$i]['gigs']['start'] = date("H:i", strtotime($acf['per_time_start']));
$showDates[$i]['gigs']['end'] = date("H:i", strtotime($acf['per_time_end']));
$showDates[$i]['gigs']['title'] = $show_title;
$showDates[$i]['gigs']['class'] = $show_day;
}
$i++;
}
}
return $showDates;
}
Any suggestions to get the output in the correct format would be more than welcome. Thanks much!
Try follwong solution. I have change your key Location1 to Location 1 because Location1 != Location 1
$json_data = '[
{"name":"Location 1","gigs":
{"start":"16:30","end":"21:15","title":"TestTitle1","class":"fri"}
},
{"name":"Location 2","gigs":
{"start":"15:00","end":"19:00","title":"TestTitle2","class":"fri"}
},
{"name":"Location 1","gigs":
{"start":"21:00","end":"22:00","title":"TestTitle3","class":"fri"}
}
]';
$arr = json_decode($json_data,true);
$new_array = array();
foreach ($arr as $key => $value) {
if(isset($new_array[$value['name']]))
$new_array[$value['name']]['gigs'][] = $value['gigs'];
else{
$new_array[$value['name']]['name'] = $value['name'];
$new_array[$value['name']]['gigs'][] = $value['gigs'];
}
}
$new_array = array_values($new_array); //to remove keys
echo json_encode($new_array);
DEMO

Return valid Json array

I'm fairly new to Json and arrays and I'm just wondering whether someone can correct the code I've tried that is still outputting an invalid string.
$json = array(
'posts' => array(),
);
while($row = mysqli_fetch_array($result)) {
$posts = array();
$posts['count'] = $rowcount;
$posts['streamitem_id'] = $row['streamitem_id'];
$json['posts'] = $posts;
echo json_encode($json);
}
I have used http://jsonlint.com/ and posted my returned data from firebug errors on lines 6,11 and 16
} {
{
"posts": {
"count": 4,
"streamitem_id": "1976"
}
} {
"posts": {
"count": 4,
"streamitem_id": "1980"
}
} {
"posts": {
"count": 4,
"streamitem_id": "1099"
}
} {
"posts": {
"count": 4,
"streamitem_id": "1178"
}
}
Some have already commented with a valid answer however, I believe array_push is the most efficient method rather than redefining the $posts variable over and over.
$json = array(
'posts' => array()
);
while($row = mysqli_fetch_array($result)) {
array_push($json['posts'], $array(
'count' => $rowcount,
'streamitem_id' => $row['streamitem_id']
)
);
}
echo json_encode($json);
PS: I noticed that you're putting $rowcount in each post array. If this is not intended, I recommend the following change:
$json = array(
'posts' => array(),
'count' => $rowcount
);
And then in the while loop:
array_push($json['posts'], $array(
'streamitem_id' => $row['streamitem_id']
)
);
This way, you can reference the post count and it won't be a waste of memory.
console.log(json['count']);
I think you want this:
$posts = array();
$rowcount = 0;
while ($row = mysqli_fetch_array($result)) {
$posts[] = array(
'count' => $rowcount,
'streamitem_id' = $row['streamitem_id'],
);
$rowcount++;
}
$json['posts'] = $posts;
echo json_encode($json);
Put this outside of loop, you are overwriting and echoing each value instead whole at once
Inside loop
$posts[] = ["count"=> $rowcount,"streamitem_id"=>$row['streamitem_id']);
After loop
$json['posts'] = $posts;
echo json_encode($json);

Creating a dynamic hierarchical array in PHP

I have this general data structure:
$levels = array('country', 'state', 'city', 'location');
I have data that looks like this:
$locations = array(
1 => array('country'=>'USA', 'state'=>'New York', 'city'=>'NYC', 'location'=>'Central Park', 'count'=>123),
2 => array('country'=>'Germany', ... )
);
I want to create hierarchical arrays such as
$hierarchy = array(
'USA' => array(
'New York' => array(
'NYC' => array(
'Central Park' => 123,
),
),
),
'Germany' => array(...),
);
Generally I would just create it like this:
$final = array();
foreach ($locations as $L) {
$final[$L['country']][$L['state']][$L['city']][$L['location']] = $L['count'];
}
However, it turns out that the initial array $levels is dynamic and can change in values and length So I cannot hard-code the levels into that last line, and I do not know how many elements there are. So the $levels array might look like this:
$levels = array('country', 'state');
Or
$levels = array('country', 'state', 'location');
The values will always exist in the data to be processed, but there might be more elements in the processed data than in the levels array. I want the final array to only contain the values that are in the $levels array, no matter what additional values are in the original data.
How can I use the array $levels as a guidance to dynamically create the $final array?
I thought I could just build the string $final[$L['country']][$L['state']][$L['city']][$L['location']] with implode() and then run eval() on it, but is there are a better way?
Here's my implementation. You can try it out here:
$locations = array(
1 => array('country'=>'USA', 'state'=>'New York', 'city'=>'NYC', 'location'=>'Central Park', 'count'=>123),
2 => array('country'=>'Germany', 'state'=>'Blah', 'city'=>'NY', 'location'=>'Testing', 'count'=>54),
);
$hierarchy = array();
$levels = array_reverse(
array('country', 'state', 'city', 'location')
);
$lastLevel = 'count';
foreach ( $locations as $L )
{
$array = $L[$lastLevel];
foreach ( $levels as $level )
{
$array = array($L[$level] => $array);
}
$hierarchy = array_merge_recursive($hierarchy, $array);
}
print_r($hierarchy);
Cool question. A simple approach:
$output = []; //will hold what you want
foreach($locations as $loc){
$str_to_eval='$output';
for($i=0;$i<count($levels);$i++) $str_to_eval .= "[\$loc[\$levels[$i]]]";
$str_to_eval .= "=\$loc['count'];";
eval($str_to_eval); //will build the array for this location
}
Live demo
If your dataset always in fixed structure, you might just loop it
$data[] = [country=>usa, state=>ny, city=>...]
to
foreach ($data as $row) {
$result[][$row[country]][$row[state]][$row[city]] = ...
}
In case your data is dynamic and the levels of nested array is also dynamic, then the following is an idea:
/* convert from [a, b, c, d, ...] to [a][b][...] = ... */
function nested_array($rows, $level = 1) {
$data = array();
$keys = array_slice(array_keys($rows[0]), 0, $level);
foreach ($rows as $r) {
$ref = &$data[$r[$keys[0]]];
foreach ($keys as $j => $k) {
if ($j) {
$ref = &$ref[$r[$k]];
}
unset($r[$k]);
}
$ref = count($r) > 1 ? $r : reset($r);
}
return $data;
}
try this:
<?php
$locations = [
['country'=>'USA', 'state'=>'New York', 'city'=>'NYC', 'location'=>'Central Park', 'street'=>'7th Ave', 'count'=>123],
['country'=>'USA', 'state'=>'Maryland', 'city'=>'Baltimore', 'location'=>'Harbor', 'count'=>24],
['country'=>'USA', 'state'=>'Michigan', 'city'=>'Lansing', 'location'=>'Midtown', 'building'=>'H2B', 'count'=>7],
['country'=>'France', 'state'=>'Sud', 'city'=>'Marseille', 'location'=>'Centre Ville', 'count'=>12],
];
$nk = array();
foreach($locations as $l) {
$jsonstr = json_encode($l);
preg_match_all('/"[a-z]+?":/',$jsonstr,$e);
$narr = array();
foreach($e[0] as $k => $v) {
if($k == 0 ) {
$narr[] = '';
} else {
$narr[] = ":{";
}
}
$narr[count($e[0]) -1] = ":" ;
$narr[] = "";
$e[0][] = ",";
$jsonstr = str_replace($e[0],$narr,$jsonstr).str_repeat("}",count($narr)-3);
$nk [] = $ko =json_decode($jsonstr,TRUE);
}
print_r($nk);
Database have three field:
here Name conatin contry state and city name
id,name,parentid
Pass the contry result to array to below function:
$data['contry']=$this->db->get('contry')->result_array();
$return['result']=$this->ordered_menu( $data['contry'],0);
echo "<pre>";
print_r ($return['result']);
echo "</pre>";
Create Function as below:
function ordered_menu($array,$parent_id = 0)
{
$temp_array = array();
foreach($array as $element)
{
if($element['parent_id']==$parent_id)
{
$element['subs'] = $this->ordered_menu($array,$element['id']);
$temp_array[] = $element;
}
}
return $temp_array;
}

php json multidimensional array syntax

I have a problem with the JSON I'm creating in PHP; I create the array in a while loop from an sql query. $featuresCSV is a comma-separated string like "1,3,4". In the JSON I need it to end up like feature-1: 1,feature-2: 1,feature-3: 1 The 1 represents true for my checkbox in my front-end program.
while ($stmt2->fetch()) {
$features = array();
$featuresTmp = explode(',', $featuresCSV, -1);
foreach ($featuresTmp as &$featureItem) {
$features[] = array("feature-" . $featureItem => 1);
}
$items[] = array('price' => $price, 'image' => $image, 'features' => $features);
}
...
json_encode($output);
The JSON ends up looking like this:
{"price":8900,
"image":"4d3f22fe-9f1a-4a7e-a564-993c821b2279.jpg",
"features":[{"feature-1":1},{"feature-2":1}]}
but I need it to look like this:
{"price":8900,
"image":"4d3f22fe-9f1a-4a7e-a564-993c821b2279.jpg",
"features":[{"feature-1":1,"feature-2":1}]}
Notice how feature-1 and feature-2 aren't separated by brackets in the second.
You need to assign the elements at "feature-1" and "feature-2".
foreach ($featuresTmp as &$featureItem) {
$features["feature-" . $featureItem] = 1;
}
The syntax $feature[] = ... is for appending to the end of an array.
Here ya go
while ($stmt2->fetch()) {
$features = array();
$featuresTmp = explode(',', $featuresCSV, -1);
foreach ($featuresTmp as &$featureItem) {
$features["feature-$featureItem"] = 1;
}
$items[] = array('price' => $price, 'image' => $image, 'features' => $features);
}
...
json_encode($output);

Create array nested PHP

Hi all' I have a page into PHP where I retrieve XML data from a server and I want to store this data into an array.
This is my code:
foreach ($xml->DATA as $entry){
foreach ($entry->HOTEL_DATA as $entry2){
$id = (string)$entry2->attributes()->HOTEL_CODE;
$hotel_array2 = array();
$hotel_array2['id'] = $entry2->ID;
$hotel_array2['name'] = utf8_decode($entry2->HOTEL_NAME);
$i=0;
foreach($entry2->ROOM_DATA as $room){
$room_array = array();
$room_array['id'] = (string)$room->attributes()->CCHARGES_CODE;
$hotel_array2['rooms'][$i] = array($room_array);
$i++;
}
array_push($hotel_array, $hotel_array2);
}
}
In this mode I have the array hotel_array which all hotel with rooms.
The problem is that: into my XML I can have multiple hotel with same ID (the same hotel) with same information but different rooms.
If I have an hotel that I have already inserted into my hotel_array I don't want to insert a new array inside it but I only want to take its rooms array and insert into the exisiting hotel.
Example now my situation is that:
hotel_array{
[0]{
id = 1,
name = 'test'
rooms{
id = 1
}
}
[0]{
id = 2,
name = 'test2'
rooms{
id = 100
}
}
[0]{
id = 1,
name = 'test'
rooms{
id = 30
}
}
}
I'd like to have this result instead:
hotel_array{
[0]{
id = 1,
name = 'test'
rooms{
[0]{
id = 1
}
[1]{
id = 30
}
}
}
[0]{
id = 2,
name = 'test2'
rooms{
id = 100
}
}
}
How to create an array like this?
Thanks
first thing is it helps to keep the hotel id as the index on hotel_array when your creating it.
foreach ($xml->DATA as $entry){
foreach ($entry->HOTEL_DATA as $entry2){
$id = (string)$entry2->attributes()->HOTEL_CODE;
$hotel_array2 = array();
$hotel_array2['id'] = $entry2->ID;
$hotel_array2['name'] = utf8_decode($entry2->HOTEL_NAME);
$i=0;
foreach($entry2->ROOM_DATA as $room){
$room_array = array();
$room_array['id'] = (string)$room->attributes()->CCHARGES_CODE;
$hotel_array2['rooms'][$i] = array($room_array);
$i++;
}
if (!isset($hotel_array[$hotel_array2['id']])) {
$hotel_array[$hotel_array2['id']] = $hotel_array2;
} else {
$hotel_array[$hotel_array2['id']]['rooms'] = array_merge($hotel_array[$hotel_array2['id']]['rooms'], $hotel_array2['rooms']);
}
}
}
Whilst this is the similar answer to DevZer0 (+1), there is also quite a bit that can be done to simplify your workings... there is no need to use array_merge for one, or be specific about $i within your rooms array.
$hotels = array();
foreach ($xml->DATA as $entry){
foreach ($entry->HOTEL_DATA as $entry2){
$id = (string) $entry2->attributes()->HOTEL_CODE;
if ( empty($hotels[$id]) ) {
$hotels[$id] = array(
'id' => $id,
'name' => utf8_decode($entry2->HOTEL_NAME),
'rooms' => array(),
);
}
foreach($entry2->ROOM_DATA as $room){
$hotels[$id]['rooms'][] = array(
'id' => (string) $room->attributes()->CCHARGES_CODE;
);
}
}
}
Just in case it helps...
And this :)
$hotel_array = array();
foreach ($xml->DATA as $entry)
{
foreach ($entry->HOTEL_DATA as $entry2)
{
$hotel_code = (string) $entry2->attributes()->HOTEL_CODE;
if (false === isset($hotel_array[$hotel_code]))
{
$hotel = array(
'id' => $entry2->ID,
'code' => $hotel_code,
'name' => utf8_decode($entry2->HOTEL_NAME)
);
foreach($entry2->ROOM_DATA as $room)
{
$hotel['rooms'][] = array(
'id' => (string)$room->attributes()->CCHARGES_CODE,
);
}
$hotel_array[$hotel_code] = $hotel;
}
}
}

Categories