PHP extract key-value in array json and restructure - php

Any idea on how to restructure the json below:
$jsonArray = [{"Level":"77.2023%","Product":"Milk","Temperature":"4"},
{"Level":"399.2023%","Product":"Coffee","Temperature":"34"},
{"Level":"109.2023%","Product":"Chocolate","Temperature":"14"}]
Expected outcome:
$expected = {"Milk":{"Level":"77.2023%","Temperature":"4"},
"Coffee":{"Level":"399.2023%","Temperature":"34"},
"Chocolate":{"Level":"109.2023%","Temperature":"14"}
}
I'm new and my thinking is get the product value in array and again use foreach loop to find the others value? .

Here's one possibility:
$jsonArray = '[{"Level":"77.2023%","Product":"Milk","Temperature":"4"},
{"Level":"399.2023%","Product":"Coffee","Temperature":"34"},
{"Level":"109.2023%","Product":"Chocolate","Temperature":"14"}]';
$output = array();
foreach (json_decode($jsonArray, true) as $row) {
$product = $row['Product'];
$output[$product] = $row;
unset($output[$product]['Product']);
}
echo json_encode($output);
Output:
{"Milk":{"Level":"77.2023%","Temperature":"4"},
"Coffee":{"Level":"399.2023%","Temperature":"34"},
"Chocolate":{"Level":"109.2023%","Temperature":"14"}
}
Demo on 3v4l.org

This made some trick
$a = '[{"Level":"77.2023%","Product":"Milk","Temperature":"4"},
{"Level":"399.2023%","Product":"Coffee","Temperature":"34"},
{"Level":"109.2023%","Product":"Chocolate","Temperature":"14"}]';
$newAr = array();
foreach(json_decode($a,true) as $key=>$value)
{
$newAr[$value['Product']] = array(
'Level' => $value['Level'],
'Temperature' => $value['Temperature'],
);
}

There are many ways to perform this with Loops in PHP. Other answers demonstrate it accurately. I would also suggest to integrate some form of Error handling, data validation/filtering/restriction in your code to avoid unexpected results down the road.
For instance, json_decode(), either assigned to a variable pre-foreach or straight in the foreach() 1st argument will just raise a warning if the original json is not valid-json, and just skip over the foreach used to construct your final goal. Then if you pass the result (that may have failed) directly to your next logic construct, it could create some iffy-behavior.
Also, on the concept of data-validation & filtering, you could restrict the foreach(), or any other looping mechanism, to check against a Product_List_Array[Milk,Coffee,Chocolate], using if(in_array() ...) so the final/goal object only contains the expected Products, this, in the case the original json has other artifacts. Filtering the values can also increase stability in restricting, for example, Temperature to Float.

Related

How do I loop through and change values in this PHP object?

Here is a fairly big object dumped using print_r.
https://docs.google.com/document/d/175RLhWlMQcyhGR6ffGSsoJGS3RyloEqo4EEHCL2H2vg/edit?usp=sharing
I am trying to change the values of the uploaded_files.
Towards the end of that object you'll see something like
[uploaded_files] => Array
(
[attachment] => /home2/magician/public_html/development/testing/wp-content/uploads/wpcf7_uploads/Central-Coast-Montessori-logo.jpg
[attachment2] => /home2/magician/public_html/development/testing/wp-content/uploads/wpcf7_uploads/Andrew.jpg )
My code
// move the attachments to wpcf7ev temp folder
foreach ($cf7ev_object['uploaded_files'] as $key => $uploaded_file_path) {
$new_filepath = WPCF7EV_UPLOADS_DIR . '/' . basename($uploaded_file_path);
wpcf7ev_debug("New file path is {$new_filepath}");
rename($uploaded_file_path, $new_filepath);
wpcf7ev_debug("'{$key}'is the KEY for {$uploaded_file_path}");
wpcf7ev_debug($cf7ev_object['uploaded_files']);
$cf7ev_object['uploaded_files'][$key] = $new_filepath; // this is not updating
}
To loop through it I have been using
foreach ($cf7ev_object->uploaded_files as $key => $uploaded_file_path) {
and this has worked.
But shouldn't it be
foreach ($cf7ev_object['uploaded_files'] as $key => $uploaded_file_path) {
? As '->' is for accessing methods?
And specifically I want to update the values of those uploaded_files, so to do that I need to do
$cf7ev_object['uploaded_files'][$key] = $new_filepath; // this is not updating
? But this doesn't seem to be working.
I think I need to be clear on how to access values in an object.
Thanks.
First of all, regarding the single arrow "->" that is how you reference an objects values. But I won't get into that. Since you say it works, $cf7ev_object is obviously an object.
You say you want to "access the values in the object".
var_dump($cf7ev_object);
This will spit out what is in that object. I gather you are a bit of a newbie, so I will try to help you out best I can with the limited data you provided (you may want to expand your question.
Looping is not a one-shot deal. You can have nested loops and nested loops inside of those. However, it is a resource hog if you're not careful. Here is an exercise that might help you.
$new_array = array();
foreach($cf7ev_object->uploaded_files as $key => $value) {
$new_value = $value;//do something to the $value here
$new_array[$key] = $new_value;
}
//take a look at your work now:
print_r($new_array);
I hope this helps. Note: your google doc is restricted, public can't see it.. And your question is too vague. Let me know if I can help more.
If you want to change the object array values instantly you just set it equal to the above loop result:
$cf7ev_object->uploaded_files = $new_array;

echo parts of json returned in php

my returned json looks like this http://pastebin.com/Nbr161s3
I want to echo
body->airTicketListResponse->routings->mainAirlineName
body->airTicketListResponse->routings->adultBasePrice
body->airTicketListResponse->routings->trips->segments->departureAirportCode
body->airTicketListResponse->routings->trips->segments->departureTime //only the time here
body->airTicketListResponse->routings->trips->segments->duration
for each routings.
How do I do this? Here is what I have but I am lost and I know it is way off.
$result = data returned here http://pastebin.com/Nbr161s3
$airTicketListResponse = $result->body->airTicketListResponse;
$routings = $result->body->airTicketListResponse->routings;
$trips = $result->body->airTicketListResponse->routings->trips;
$segments = $result->body->airTicketListResponse->routings->trips->segments;
foreach($airTicketListResponse as $item){
$i=0;
$i<count($routings);
echo '<span style="font-weight:bold;">Airline - '.$item->routings[i]->mainAirlineName.' Price - '.$item->routings[i]->adultBasePrice.'</span><br />'.$item->routings[i]->trips[i]->segments[i]->departureAirportCode.' '.$item->routings[i]->trips[i]->segments[i]->departureTime.'<br /><br />';
$i++;
}
Please help if you can.
Before working with JSON you should be familiar with working with arrays and objects since JSON is nothing more than that.
It seems you already know these two concepts
To access an object property in PHP you use obj->property
To access a value of an array you specify the index inside brackets array[0]
With JSON you just have to keep in mind that some of your object properties will be arrays.
Now, since your data comes in a multi-level three-like structure you should also be familiar with traversing arrays, PHP offers an implementation of a foreach loop that is ideal for traversing dynamically generated arrays
using foreach($array as $index => $var) the $index and $var variables are automatically set to the index and value of each element in the array as they are being traversed, so you don't manually need to keep track of the index (i.e. $i)
Now let's start going through your data:
First we find your routings array
$result = json_decode($data);
$airTicketListResponse = $result->body->airTicketListResponse;
$routings = $airTicketListResponse->routings;
Now we use foreach to loop through every routing and print the needed properties
foreach($routings as $routing){ //$routing will hold the object value in each loop
echo 'Airline '.$routing->mainAirlineName.'<br>';
echo 'Adult Base Price '.$routing->adultBasePrice.'<br>';
}
Getting single properties like the above is pretty straight forward, but for the information of the segments we would first need a nested foreach since we have multiple trips for each routing and then a second nested foreach since each trip has multiple segments
foreach($routings as $routing){ //$routing will hold the object value in each loop
echo 'Airline '.$routing->mainAirlineName.'<br>';
echo 'Adult Base Price '.$routing->adultBasePrice.'<br>';
foreach($routing->trips as $trip){
foreach($trip->segments as $index => $segment){
echo 'Segment '.$index.':<br>'
echo 'Depart From '.$segment->departureAirportCode.'<br>';
echo 'Departure Time '.$segment->departureTime.'<br>';
echo 'Duration '.$segment->duration.'<br>';
}
}
}
And that would be it. I hope my explanation was clear and you got the idea of how to traverse JSON objects
If you feel more comfortable working with an array than with an object to access your data [which might be where you're getting confused here] then you can use json_decode with an additional argument:
$data = json_decode($result, true);
This will leave you with an array ($data) containing all your flight information, you can then var_dump() it and see the hierarchy you're dealing with and loop through it.

How to use JSON with unknown multiple keys (PHP)

I am receiving a JSON String, which has multiple unknown keys. It's pretty hard to explain, because those JSON strings are pretty large, I'll try to break them down in the most efficient way.
I use PHP to break down the object, that I get, when I decode the JSON string.
$data1 = $json->result->map->12313214654[0]
$data2 = $json->result->map->12313214654[2]
$differentdata1 = $json->result->map->12313214655[0]
As you can see, there are different subsections after the map key.
Those are numbers, that are pretty random. And their appearance isn't regular either. So sometimes there's just one subsection (or number), and sometimes more.
How can I access them? I tried to use $datacount = $count($json->result->map) But it always displays 1. And then I still wouldn't be able to access the subelements of the map key.
Does anyone have a solution for this?
As you seem to have an unknown amount of data in array form, you could iterate your results with a foreach loop:
foreach ($json->result->map as $key => $dataArray) {
// $key will be the numeric key, e.g. 12313214654
// $dataArray will be the array of data you're after
foreach ($value as $dataIndex => $data) {
// $dataIndex is the position of $data within the $dataArray
// $data is the value you were trying to access with $json->result->map->12313214654[n]
// You do your work with $data here.
print_r($data);
}
}

Difference between array_push() and $array[] =

In the PHP manual, (array_push) says..
If you use array_push() to add one element to the array it's better to
use $array[] = because in that way there is no overhead of calling a
function.
For example :
$arr = array();
array_push($arr, "stackoverflow");
print_r($arr);
vs
$arr[] = "stackoverflow";
print_r($arr);
I don't understand why there is a big difference.
When you call a function in PHP (such as array_push()), there are overheads to the call, as PHP has to look up the function reference, find its position in memory and execute whatever code it defines.
Using $arr[] = 'some value'; does not require a function call, and implements the addition straight into the data structure. Thus, when adding a lot of data it is a lot quicker and resource-efficient to use $arr[].
You can add more than 1 element in one shot to array using array_push,
e.g. array_push($array_name, $element1, $element2,...)
Where $element1, $element2,... are elements to be added to array.
But if you want to add only one element at one time, then other method (i.e. using $array_name[]) should be preferred.
The difference is in the line below to "because in that way there is no overhead of calling a function."
array_push() will raise a warning if the first argument is not
an array. This differs from the $var[] behaviour where a new array is
created.
You should always use $array[] if possible because as the box states there is no overhead for the function call. Thus it is a bit faster than the function call.
array_push — Push one or more elements onto the end of array
Take note of the words "one or more elements onto the end"
to do that using $arr[] you would have to get the max size of the array
explain:
1.the first one declare the variable in array.
2.the second array_push method is used to push the string in the array variable.
3.finally it will print the result.
4.the second method is directly store the string in the array.
5.the data is printed in the array values in using print_r method.
this two are same
both are the same, but array_push makes a loop in it's parameter which is an array and perform $array[]=$element
Thought I'd add to the discussion since I believe there exists a crucial difference between the two when working with indexed arrays that people should be aware of.
Say you are dynamically creating a multi-dimensional associative array by looping through some data sets.
$foo = []
foreach ($fooData as $fooKey => $fooValue) {
foreach ($fooValue ?? [] as $barKey => $barValue) {
// Approach 1: results in Error 500
array_push($foo[$fooKey], $barKey); // Error 500: Argument #1 ($array) must be of type array
// NOTE: ($foo[$fooKey] ?? []) argument won't work since only variables can be passed by reference
// Approach 2: fix problem by instantiating array beforehand if it didn't exist
$foo[$fooKey] ??= [];
array_push($foo[$fooKey], $barKey);
// Approach 3: One liner approach
$foo[$fooKey][] = $barKey; // Instantiates array if it doesn't exist
}
}
Without having $foo[$fooKey] instantiated as an array beforehand, we won't be able to do array_push without getting the Error 500. The shorthand $foo[$fooKey][] does the heavy work for us, checking if the provided element is an array, and if it isn't, it creates it and pushes the item in for us.
I know this is an old answer but it might be helpful for others to know that another difference between the two is that if you have to add more than 2/3 values per loop to an array it's faster to use:
for($i = 0; $i < 10; $i++){
array_push($arr, $i, $i*2, $i*3, $i*4, ...)
}
instead of:
for($i = 0; $i < 10; $i++){
$arr[] = $i;
$arr[] = $i*2;
$arr[] = $i*3;
$arr[] = $i*4;
...
}
edit- Forgot to close the bracket for the for conditional
No one said, but array_push only pushes a element to the END OF THE ARRAY, where $array[index] can insert a value at any given index. Big difference.

Make 1d Array from 1st member of each value in 2d Array | PHP

How can you do this? My code seen here doesn't work
for($i=0;i<count($cond);$i++){
$cond[$i] = $cond[$i][0];
}
It can be as simple as this:
$array = array_map('reset', $array);
There could be problems if the source array isn't numerically index. Try this instead:
$destinationArray = array();
for ($sourceArray as $key=>$value) {
$destinationArray[] = $value[0]; //you may want to use a different index than '0'
}
// Make sure you have your first array initialised here!
$array2 = array();
foreach ($array AS $item)
{
$array2[] = $item[0];
}
Assuming you want to have the same variable name afterwards, you can re-assign the new array back to the old one.
$array = $array2;
unset($array2); // Not needed, but helps with keeping memory down
Also, you might be able to, dependant on what is in the array, do something like.
$array = array_merge(array_values($array));
As previously stated, your code will not work properly in various situation.
Try to initialize your array with this values:
$cond = array(5=>array('4','3'),9=>array('3','4'));
A solution, to me better readable also is the following code:
//explain what to do to every single line of the 2d array
function reduceRowToFirstItem($x) { return $x[0]; }
// apply the trasnformation to the array
$a=array_map('reduceRowTofirstItem',$cond);
You can read the reference for array map for a thorough explanation.
You can opt also for a slight variation using array_walk (it operate on the array "in place"). Note that the function doesn't return a value and that his parameter is passed by reference.
function reduceToFirstItem(&$x) { $x=$x[0]; }
array_walk($cond, 'reduceToFirstItem');
That should work. Why does it not work? what error message do you get?
This is the code I would use:
$inArr;//This is the 2D array
$outArr = array();
for($i=0;$i<count($inArr);$i++){
$outArr[$i] = $inArr[$i][0];
}

Categories