Loop trough a nested json array in PHP - php

I need to loop trough a nested JSON array in PHP. The JSON keys are not always the same, see example below:
[
{
"id": 1,
"more": {
"city": "New York",
"street": "W 58th St"
},
"group": 4,
"name": "Ellie",
"status": "offline",
"phone": "1234567890",
"disabled": false
},
{
"id": 2,
"more": {
"city": "New York",
"street": "W 101st St",
"postal code": "12345"
},
"group": 7,
"name": "Diane",
"age": "25",
"phone": "",
"contact": "2",
}
]
My code so far is this:
$user_details = json_decode($json, true);
foreach ($user_details as $details) {
foreach ($details as $key => $value) {
echo $key .': '. $value, PHP_EOL;
}
}
The problem is, I get an error for the more array when I try to run the code above:
id: 1
<b>Warning</b>: Array to string conversion in <b>[...][...]</b> on line <b>15</b><br />
more: Array
group: 4
name: Ellie
status: offline
...
Ideally, the output should be like so:
id: 1
city: New York
street: "W 58th St
group: 4
name: Ellie
status: offline
...
Any suggestion on how to improve my code to output the correct data?

You have 3 arrays. For example, look at your first item, where id = 1. For 'more', you have:
$user_details[0]['more']['city'] = 'New York';
Your outer loop grabs elements 0 thru 1. The inner loop has keys = 'id', 'more', 'group', 'name', etc. When you try to execute echo the 2nd time, your variables are:
$key = 'more';
$value = [ 'city' => 'New York', 'street' => 'W 58th St' ];
Your echo statement tries to treat $value as a string, but it's an array.
Wrap your echo statement in an if () statement, such that:
if ( is_array( $value ) ) {
// For an array, do something different
foreach ( $value as $key1 => $value1 ) {
echo $key1 . ': ' . $value1, PHP_EOL
}
} else {
// Do your echo here.
echo $key .': '. $value, PHP_EOL;
}

This line echo $key .': '. $value, PHP_EOL; is treating a value of type array as a string as it is concatenating the value to a string.
Instead, you could do something like this to check if the value is itself an array, and then print each member of it if so.
if ( is_array($value) ) {
// One more nested loop to print the keys and values
}
Of course, if there are any other nested objects or arrays, you will run into the same problem. So better to implement some type of logic to handle nested objects or arrays in general.

Related

How to fetch Array from .json in PHP

I have json document with Indian States[Cities[Area]], similar to the following:
{
"Andaman and Nicobar Islands": [{
"Port Blair": [
"Aberdeen Bazaar",
"Bidhabad Village",
"Chidiyatapu",
"Corbyns Cove",
"Dollygunj",
"Ferrurgunj",
"Goalghar",
"Goodwill Estate",
"Junglighat",
"Marine Hill",
"Phoenix Bay",
"South Point"
]
},
{
"Havelock Island": [
"Govindnagar Beach",
"Radhanagar Beach",
"Vijaynagar Beach"
]
},
{
"Neil Island": [
"Ramnagar",
"Bharat Pur",
"Sitapur Beach",
"Laxmanpur",
"Neil Kendra"
]
}....
}
I want to fetch this array in this format:
$stateData['Andaman and Nicobar Islands'] => [
"Port Blair" => [
"Aberdeen Bazaar" => "Aberdeen Bazaar",
"Bidhabad Village" => "Bidhabad Village"
.
.
.
]
]
and so on...
I have this Json data in a json file and assign the value to a variable $stateData using $stateData = (array)json_decode(fread($file, filesize(public_path('india_state_city1.json'))));
I assume that your json is saved in a variable called $states.
foreach (json_decode($states) as $key => $state) {
foreach ($state as $stateData) {
foreach ($stateData as $key2 => $city) {
foreach ($city as $key3 => $cit) {
$res[$key][$key2][$cit] = $cit;
}
}
}
}
The output:
Check the Demo: https://paiza.io/projects/NlK9g5jluy8Lz9kmhMW69Q
i got that you want to make the area array to be associative and the id,value is same.
i f i'm right you can do this :
foreach ($stateData['Andaman and Nicobar Islands'] as &$array_1) {
foreach ($array_1 as &$area_array){
$formatted_array = [];
foreach ($area_array as $area){
$formatted_array[$area] = $area;
}
$area_array = $formatted_array;
}
}
long but simple solution i think
in my opinion json_decode function will help with second parameter passed as true
because it will convert every inner object to array
by converting to array we can easily use the state,city and area name and if you want ordering even you can do that by key no of array
<?php
$data = '{
"Andaman and Nicobar Islands": [
{
"Port Blair": [
"Aberdeen Bazaar",
"Bidhabad Village",
"Chidiyatapu",
"Corbyns Cove",
"Dollygunj",
"Ferrurgunj",
"Goalghar",
"Goodwill Estate",
"Junglighat",
"Marine Hill",
"Phoenix Bay",
"South Point"
]
},
{
"Havelock Island": [
"Govindnagar Beach",
"Radhanagar Beach",
"Vijaynagar Beach"
]
},
{
"Neil Island": [
"Ramnagar",
"Bharat Pur",
"Sitapur Beach",
"Laxmanpur",
"Neil Kendra"
]
}
]
}';
$indian_states = json_decode($data,TRUE);
foreach ($indian_states as $stateName=>$statesCities)
{
echo $stateName;
foreach ($statesCities as $citiNo=>$cityAreas)
{
echo '<br /> |---'; //comment this line
foreach ($cityAreas as $citiName=>$areas)
{
echo $citiName;
foreach ($areas as $areaName){
echo "<br /> |---"; //comment this line echo $areaName;echo '<br />';
}
}
}
}
?>
output

Loop through foreach without knowing the index

I would like to Loop throught services but I don't know the index name. They come randomly, example I got 8 and 9 but I do not know them.
"2": {
"first_name": "khalfan",
"last_name": "mussa",
"date": "2017-06-06 09:21:36",
"gender": "male",
"services": {
"8": {
"name": "See a Doctor",
"results": ""
},
"9": {
"name": "Kichocho",
"results": "FD- 73"
}
}
},
From #Alive to Die answer, I made some changes and I think this code will loop in your services no matter the index.
$array = json_decode($json, true);
foreach ($array as $values) {
foreach ($values as $keys => $value) {
if (is_array($value)) {
foreach ($value as $key => $val) {
if (is_array($val)) {
foreach ($val as $k => $v) {
echo $k . ":" . $v . "\n";
}
}
}
}
}
}
Suppose you have json stored in $json variable.
$json = json_decode($json);
foreach($json as $entry) {
foreach($entry['services'] as $services) {
//$services['name']
//and other data here
}
}
You don't need to know the index while using foreach but you can get index from it.
The following are four available options:
<?php
$arr = ["2" => [
["first_name"=> "khalfan",
"last_name"=> "mussa",
"date"=>"2017-06-06 09:21:36",
"gender"=> "male"],
["services" =>
["8" => ["name" => "See a Doctor","results"=> ""],
"9" => ["name"=> "Kichocho","results"=> "FD- 73"]
]
]
]];
for ($i=0, $max=count($arr["2"]); $i < $max; $i++) {
if ( isset( $arr["2"][$i]["services"])) {
$a = $arr["2"][$i]["services"];
foreach($a as $e) {
echo $e["name"],"\t";
echo $e["results"],"\n";
}
}
continue;
}
See live code
The advantage here is that the code does work with a foreach as per the OP's request. But the code is involved and not as fast as it could be, owing to that if conditional.
Another solution that is faster:
<?php
$arr = ["2" => [
["first_name"=> "khalfan",
"last_name"=> "mussa",
"date"=>"2017-06-06 09:21:36",
"gender"=> "male"],
["services" =>
["8" => ["name" => "See a Doctor","results"=> ""],
"9" => ["name"=> "Kichocho","results"=> "FD- 73"]
]
]
]];
$count = count($arr["2"]);
$last = $count - 1; // b/c of zero-based indexing
foreach ($arr as $e) {
foreach($e[$last]["services"] as $a) {
echo $a["name"],"\t";
echo $a["results"],"\n";
}
}
// Or an easier solution without resorting to foreach:
array_walk_recursive($arr,function($item,$key) {
if ($key == "name") echo $item,"\t";
if ($key == "results") echo $item,"\n";
});
See live code
Whether $arr["2"] contains two elements or more as long as the last one is the "services" associate array, this foreach code works. But, this type of "array walk" can best be carried out with a built-in function designed for this very purpose, array_walk_recursive. With this function, you don't have to worry about how to construct the perfect foreach; the iteration occurs behind the scenes and all you need is to supply a callback. array_walk_recursive will drill down to the "services" element and if there is one or more associative arrays with keys of "name" and "results", then their respective values display.
The fourth possibility is one of those "why would you" situations. Why take an array and json_encode it and then json_decode it back to an array and then apply array_walk_recursive? But, the code does work:
<?php
$arr = ["2" => [
["first_name"=> "khalfan",
"last_name"=> "mussa",
"date"=>"2017-06-06 09:21:36",
"gender"=> "male"],
["services" =>
["8" => ["name" => "See a Doctor","results"=> ""],
"9" => ["name"=> "Kichocho","results"=> "FD- 73"]
]
]
]];
$result=json_decode(json_encode($arr),true);
array_walk_recursive($result, function($value,$key){
if ($key == "name" ) { echo $value,"\t";}
if ($key == "results") { echo $value,"\n";}
});
See live code

Convert nested array into comma separated list of values

I have a simple bit of JSON like this:
{
"grinning": {
"unicode": "1f600",
"unicode_alternates": "",
"name": "grinning face",
"shortname": ":grinning:",
"category": "people",
"emoji_order": "1",
"aliases": [
],
"aliases_ascii": [
],
"keywords": [
"happy",
"joy",
"smile",
"grin",
"smiling",
"smiley",
"person"
]
},
"grimacing": {
"unicode": "1f62c",
"unicode_alternates": "",
"name": "grimacing face",
"shortname": ":grimacing:",
"category": "people",
"emoji_order": "2",
"aliases": [
],
"aliases_ascii": [
],
"keywords": [
"teeth",
"grimace",
"disapprove",
"pain",
"person"
]
}
}
I can access the "unicode" and "name" elements via:
<?php
$str = file_get_contents('http://localhost/_testing/emoji/emoj1-test.json');
$json_a = json_decode($str, true);
foreach($json_a as $key => $val) {
echo $val['unicode'];
echo $val['name'];
}
?>
But I can't work out how I can get the "keywords" nested array into a variable containg the keywords held as a comma separated list of values.
I simplistically tried:
echo $val['keywords'];
But because that's an array, it returns this error:
Notice: Array to string conversion
I then tried:
echo $val['keywords'][0];
Which I think is along the right lines, but still doesn't return any data.
echo implode(',', $val['keywords']);
Try with join,
foreach($json_a as $key => $val){
echo join(", ", $val['keywords']);
}
The following works up to 2 levels of nesting. You can iterate and print the entire nested array with it.
<?php
$arr = ['Your JSON'];
foreach ($arr as $key => $value) {
$string = is_array($value) ? implode(",", $value) : $value;
echo $string;
}
?>

PHP array to be the same out to JSON format structure

Here's what I want to do in my php array to be exact json format below:
JSON
{
"suggestions": [
{ "value": "Alex - alex#email.com", "data": {"id": 1, "name": Alex } },
{ "value": "John - john#email.com", "data": {"id": 2, "name": John } },
{ "value": "Diaz - diaz#email.com", "data": {"id": 3, "name": Diaz } }
]
}
Query result in my php array:
array(
0 => array('id'=>'1' 'email'=>'alex#email.com', 'name'=>'Alex'),
1 => array('id'=>'2' 'email'=>'john#email.com', 'name'=>'John'),
2 => array('id'=>'3' 'email'=>'diaz#email.com', 'name'=>'Diaz')
);
Do you have any idea how will you make my php array to that JSON format way?
You can simply use json_encode(); function for that.
json_encode($array);
This should help you for your JSON format
foreach($query as $key => $val){
$json[$key]['value'] = $val['name']." - ".$val['email'];
$json[$key]['data']["id"] = $val['id'];
$json[$key]['data']["name"] = $val['name'];
}
echo json_encode($json);
foreach ($your_array as $key => $val) {
foreach ($val as $k => $v) {
if ($v == 'email') {
//get the value of 'email' key in 'value'
$newArr['suggestions']['value'] = current($v);
}
else {
//if value is not email push it in 'data' key
$newArr['suggestions']['data'] = $v;
}
}
}
//lastly encode the required array
echo json_encode($newArr);

How to get values from nested JSON data?

Here's my JSON code:
{
"query": {
"count": 2,
"created": "2013-04-03T09:47:03Z",
"lang": "en-US",
"results": {
"yctCategories": {
"yctCategory": {
"score": "0.504762",
"content": "Computing"
}
},
"entities": {
"entity": [
{
"score": "0.902",
"text": {
"end": "19",
"endchar": "19",
"start": "0",
"startchar": "0",
"content": "Computer programming"
},
"wiki_url": "http://en.wikipedia.com/wiki/Computer_programming"
},
{
"score": "0.575",
"text": {
"end": "51",
"endchar": "51",
"start": "41",
"startchar": "41",
"content": "programming"
}
}
]
}
}
}
}
and below is my PHP code
$json_o = json_decode($json,true);
echo "Json result:</br>";
echo $json; // json
echo "</br></br>";
echo "Value result:</br>";
$result = array();
//$entity = $json_o['query']['results']['entities']['entity'];
foreach ($json_o['query']['results']['entities']['entity'] as $theentity)
foreach ($theentity['text'] as $thetext){
$result[] = $thetext['content'];
}
print_r($result);
My expectation is to get the value of content in entity, which is "Computer programming" and "programming".
I already searching around, but still have found the solution yet.
The result of my PHP code is:
Array ( [0] => 1 [1] => 1 [2] => 0 [3] => 0 [4] => C [5] => 5 [6] => 5 [7] => 4 [8] => 4 [9] => p )
Use this loop
foreach ($json_o['query']['results']['entities']['entity'] as $theentity)
{
$result[] = $theentity['text']['content'];
}
http://codepad.viper-7.com/tFxh1w
Output Array ( [0] => Computer programming [1] => programming )
Change your foreach to:
$result = array();
foreach ($json_o['query']['results']['entities']['entity'] as $theentity) {
$result[] = $theentity['text']['content'];
}
print_r($result);
$theentity['text'] is an array of keys => value. You can just access key content instead of looping through all of the entries.
Another way you could do it (though it is a poor choice) is:
foreach($theentity['text'] as $key => $value) {
if( 'content' === $key ) {
$result[] = $value;
}
}
I provide this second example to demonstrate why the original code did not work.
Update
To access other properties like the yctCategories just do something similar
$categories = array();
foreach ($json_o['query']['results']['yctCategories'] as $yctCategory) {
$categories[] = $yctCategory['content'];
}
print_r($categories);
remove the second foreach and replace it with $result[] = $theentity['text']['content'];
using something like http://jsonlint.com/ might make it easier for you to see how the json is structured. alternatively just var_dump (or print_r) the output of your json_decode.
Use simple code:
$array = $json_o['query']['results']['entities']['entity'];
foreach($array as $v){
echo $v['text']['content'];
}

Categories