Access array inside JSON element using PHP [duplicate] - php

This question already has an answer here:
How to extract and access data from JSON with PHP?
(1 answer)
Closed last year.
How do I access an array nested inside a JSON element with PHP. Here is the code I'm using (simplified for the example), I can access from_email, html, subject etc. easily, but how would I access the to email address recipient#addresshere.co.uk? Do I need some sort of foreach loop, on the basis that there could be more than one entry?
JSON
{
"event": "inbound",
"msg": {
"dkim": {},
"email": "myemail#addresshere.co.uk",
"from_email": "example.sender#mandrillapp.com",
"headers": {},
"html": "This is an example inbound message.",
"raw_msg": "Received: from mail115.us4.mandrillapp.com",
"sender": null,
"spam_report": {},
"spf": {},
"subject": "This is an example webhook message",
"tags": [ ],
"template": null,
"text": "This is an example inbound message.",
"text_flowed": false,
"to": [
[
"recipient#addresshere.co.uk",
null
]
]
}
}
PHP
$emailp = urldecode($_REQUEST['mandrill_events']); // The above JSON
$email = array_pop(json_decode($emailp));
$from_email = $email->msg->from_email; // From email
$html = $email->msg->html; // HTML Message
$subject = $email->msg->subject; // Subject
$to = ????
Thanks

You would access the to like this
$email->msg->to[0][0];
If you want to loop around the whole array you could do
foreach ($email->msg->to[0] as $i=>$v) {
echo "i = $i and v = $v\n";
}
Or if you wanted to loop the whole to structure you could
foreach ($json->msg->to as $i=>$v) {
foreach ($v as $ii=>$vv) {
echo "ii = $ii - vv = $vv\n";
}
}

You could, as you suggest, loop through the array with foreach. For example this would echo the "to" addresses:
$to_arr = $email->msg->to[0];
foreach($to_arr as $to) {
echo 'TO = '.$to.'<br />';
}

Using true as second function parameter, objects will be converted into associative arrays.
$email = json_decode($emailp, true);
Then you can easily access any data from the array, even use foreach if needed.
print_r($email['msg']['to']);
Resuling in
Array ( [0] => Array ( [0] => recipient#addresshere.co.uk [1] => ) )

It depends on what you expect from the data. Since it's an array, it could have 0 or more elements in it. How do you plan to deal with all the cases? If you expect to only even have one, just take the first element. If you want all of the emails in an array then take the entire thing $to = $email->msg->to;.
If you're going to use this information to fire of actual emails, then yes, you do want to iterate over all the elements.
$msg = new Email();
$msg->setSubject($subject);
// more logic
foreach($recepients as $recepient) {
// assuming element 0 is email and element 1 is name
$msg->addRecepient($recepient[0], $recepient[1]);
}

Related

Access JSON objects value in PHP without a loop [duplicate]

This question already has answers here:
How to find entry by object property from an array of objects?
(13 answers)
Closed 1 year ago.
I wonder how to access objects' values without a loop in a JSON file like this:
{
"adresse": "",
"longitude": "12.352",
"latitude": "61.2191",
"precision": "",
"Stats": [
{
"id": "300",
"carte_stat": "1154€",
},
{
"id": "301",
"carte_stat": "1172€",
},
{
"id": "302",
"carte_stat": "2293€",
},
],
}
I'd like to target for example the object with id '301'.
Using a loop I do like this:
foreach($result_json['Stats'] as $v) {
if ($v['id'] == "301") {
...
}
};
But How can I do without loop?
I tried things like this but in vain:
$result_json['Stats'][id='301']['carte_stat'];
$result_json['Stats']['id']->{'301'};
An alternative with array_filter.
Get the first occurence of id 301:
$json = json_decode($json, true);
$result = current(array_filter($json['Stats'], function($e) {
return $e['id'] == 301;
}));
print_r($result);
For/foreach will probably be faster. You shouldn't aim for "ligther code" when it will be a problem for readability or performance. Sometimes, more is less (problems).
You could index the Stats using array_column() to convert it. It's less efficient than a loop as it will first convert the entire array before you can access it by the id...
$stats = array_column($result_json['Stats'], "carte_stat", "id");
echo $stats['301'];
Note that I have to fix your JSON, but I assume this was due to chopping out data not needed for the question.

PHP - Deleting an element of a JSON array changes the array syntax

I can successfully delete elements of a JSON array with PHP, but I cannot understand why the JSON array changes syntax after deleting an element that's not the last one.
So, here's my User.json file:
[
{
"id": "kS79BhPx"
},
{
"id": "ycC7km7A"
},
{
"id": "hgF5D4es"
}
]
Here's my delete.php script:
$className = "Users";
// get the index
$index = (int)$_GET['index'];
//fetch data from json
$data = file_get_contents($className. '.json');
$data_array = json_decode($data, true);
// delete the row with the index
unset($data_array[$index]);
//encode back to json
$data = json_encode($data_array, JSON_PRETTY_PRINT);
file_put_contents($className. '.json', $data);
So, if I go to the following URL, just to test my php function:
https://example.com/delete.php?index=0
The script successfully deletes the first element of the JSON array, but then it changes into this:
{
"1": {
"id": "ycC7km7A"
},
"2": {
"id": "hgF5D4es"
}
}
Instead, if I set https://example.com/delete.php?index=2 - so I want to delete the last array's element - it saves it as follows:
[
{
"id": "kS79BhPx"
},
{
"id": "ycC7km7A"
}
]
This last result is what I need to achieve all the times I delete an element because I need the JSON array syntax to stay as [...], not as {...}.
What am I doing wrong in my PHP script?
Using unset() on an array (associative or not) in PHP will preserve the existing keys making the array associative. You need to reindex the array after using unset():
// delete the row with the index
unset($data_array[$index]);
$data_array = array_values($data_array);

How to access JSON element using regex or array index in PHP

I am trying to read JSON elements "unit" and "value" using PHP. However, some JSON elements ("local/sysbench-cpu-1.0.0", "m4.4xlarge-4.4.0-66-generic") may not be the same in each JSON. That is why I want to use regex or the array index to access elements rather then a particular string:
{
"title": "cputests-sysbench-cpu-100-m4-4xlarge-20170328",
"results": {
"local\/sysbench-cpu-1.0.0": {
"arguments": "cpu performance benchmark",
"units": "seconds",
"results": {
"m4.4xlarge-4.4.0-66-generic": {
"value": "53.2386"
}
}
},
"": {
"arguments": "Memory Usage Monitor",
"units": "Megabytes",
"results": {
"m4.4xlarge-4.4.0-66-generic": {
"value": "1355,1356,1357,1357,1358,1359,1358,1359,1359,1358,1357,1358,1369,1370,1374,1373,1374,1376,1370,1362,1359,1360,1358,1358,1357,1358,1360,1360,1359,1359,1362,1362,1362,1363,1362,1363,1366,1365,1369,1366,1365,1363,1362,1363,1362,1363,1363,1363,1368,1374,1373,1372,1372,1373"
}
}
}
}
}
The PHP script works if I don't use regex or array index:
<?php
$string = file_get_contents("result.json"); <br>
$data = json_decode($string); <br>
//$data = json_decode($string, true);
//var_dump(json_decode($string)); <br>
print $data->{'results'}->{**'local/sysbench-cpu-1.0.0'**}->units; <br>
print "\n";<br>
print $data->{'results'}->{'local/sysbench-cpu-1.0.0'}->{'results'}->{'**m4.4xlarge-4.4.0-66-generic**'}->value; <br>
// print $data['results']['local/sysbench-cpu-1.0.0']['units']; <br>
// print "\n"; <br>
// print $data['results']['local/sysbench-cpu-1.0.0']['results']['m4.4xlarge-4.4.0-66-generic']['value']; <br>
?>
Any attempt to use regex in place of a string or array index when using json_decode($string, true) fails.
You can use a foreach loop to go over the results...
foreach ($json->results as $key => $results) {
...
// access to $results->units
foreach ($results as $x => $item) {
...
// access to $item->value
}
}
Then it won't matter what they key is. Something along those lines.
PHP's JSON parsing only returns a plain old associative array, or an object. Neither of these support using regexes as lookups. If you insist on using native PHP, you'll have to foreach your way through the keys and values.
Or, you might take a look at something like JsonPath which allows you to load up JSON, and then use a query string that looks very close to shell globbing:
$data = ['people' => [['name' => 'Joe'], ['name' => 'Jane'], ['name' => 'John']]];
$result = (new JSONPath($data))->find('$.people.*.name'); // returns new JSONPath
So in your case, your find() string would be something like $.results.*.units for the unit values, and $.results.*.results.*.value for the values. There's probably an even fancier query string that would return both units and values at the same time.

Accessing value inside multi-dimension JSON array using PHP

I read several posts on here and have been unable to find success in resolving the problem I am having.
I am trying to figure out how to get the NAME field from the UploadImage array.
I have the following JSON being passed to me from a Webhook.
{
"$version":5,
"Entry":{
"Number":"11",
"Order":null,
"Origin":
{
"City":"Portland",
"CountryCode":"US",
}
,
"Message":"the message",
"UploadImage":[
{
"ContentType":"image/png",
"Id":"F-lMbiCYdwiYS8ppkQS4gsyE",
"Name":"Screen.png",
"Size":55907
}
],
"Subject":"here is the subject"
}
I have no problem grabbing the value of Subject or Message, but I cannot figure out how to grab the NAME within UploadImage.
$contact = json_decode($json);
$subject=$contact->{'Subject'};
When I do
$uploadimage=$contact->{'UploadImage'};
it just writes out ARRAY.
I can do
echo $contact->{'Entry'}->{'Number'};
and it works, so it has to be something with the bracket being there before the curly bracket. I know this has to be something simple that I am missing.
Any help is GREATLY appreciated.
$uploadimage=$contact->{'UploadImage'}[0]->{'Name'};
Firstly try
$contact = json_decode($json, true);
Adding the second argument returns an array instead of an object which will make things easier. Objects with numerical keys are troublesome... Now you can,
print_r($contact);
to see exactly what you've got. I imagine that
echo $contact['UploadImage'][0]['Name'];
Will get you what you're looking for.
Notice that UploadImage contains an array of objects (or an array of arrays after conversion).
another solution is:
$contact = json_decode($text);
$name = '';
foreach($contact->UploadImage as $k=>$v){
foreach($v as $k2=>$v2){
echo $k2.' - '.$v2.'<br />';
if($k2=='Name'){ $name = $v2;}
}
};
var_dump($name);
//response
ContentType - image/png
Id - F-lMbiCYdwiYS8ppkQS4gsyE
Name - Screen.png
Size - 55907
//name
string 'Screen.png' (length=10)
Have you try to use like below:
$uploadimage=$contact->UploadImage[0]->Name;
In JSON the square braces [] mark an array section and the curly braces {} mark an object. In your JSON string UploadImage is an array, which contains a single object.
Try changing your JSON as follows:
{
"$version": 5,
"Entry": {
"Number": "11",
"Order": null,
"Origin": {
"City": "Portland",
"CountryCode": "US"
},
"Message": "the message",
"UploadImage": {
"ContentType": "image/png",
"Id": "F-lMbiCYdwiYS8ppkQS4gsyE",
"Name": "Screen.png",
"Size": 55907
},
"Subject": "here is the subject"
}
}

Decoding Nested JSON in PHP

Excuse me if this has been covered, but I've looked and can't find an answer that works.
I have the following JSON (shortened for clarity):
[{
"header": {
"msg_type": "0001"
},
"body": {
"event_type": "ARRIVAL",
"train_id": "384T22MJ20"
}
},{
"header": {
"msg_type": "0003"
},
"body": {
"event_type": "DEPARTURE",
"train_id": "382W22MJ19"
}
}]
Now I know I can use json_decode to create a php array, but not knowing much about php I don't know how to get it to do what I want. I need to be able to access a value from each array. For example I would need to extract the train_id from each array. At the moment I have this:
$file = "sampleData.json";
$source = file_get_contents($file);
$data = json_decode($source);
$msgbdy = $data->body;
foreach($msgbdy as $body){
$trainID = $body->train_id;
}
I know this is wrong, but I'm not sure if I'm on the right track or not.
Thanks in advance.
anonymous objects are deserialized as array-members, foreach can handle that :
$objs = json_decode($source)
foreach($objs as $obj)
{
$body = $obj->body; //this is another object!
$header = $obj->header; //yet another object!
}
and within that loop, you can now access msg_type, train_id and event_type via $body and $header
I suggest to pass it true as a parameter, it is easier to work with associative arrays than objects:
$messages = json_decode($source, true);
foreach($messages as $message){
$trainID = $message["body"]["train_id"];
}
You process it in the wrong order: your string is an array of objects. Not an object with arrays.
You first need the large foreach loop to iterate over the array and then access for each element the "body" and "train_id".
Your code should thus read:
foreach($data as $item) {
echo $item->body->train_id; //or do something else with $item->body->train_id
}
Maybe something like:
$data = json_decode($source);
foreach ($data as $message) {
$trainId = $message->body->train_id;
// Not sure what you want to do wit this ^
}
You need to loop over each whole entry. See how where the data is repeated, and that is what you need to loop over.
Your trying to access an array like an object. The array notation would be $data[0]['body'] to retrieve the value for the "body" key in the first entry in the array.

Categories