Get data from a nested JSON in PHP using Recursion and Loops

Posted on 06th May 2020

A JSON document can have JSON objects nested inside other JSON objects. JSON objects are key-value pairs and there are different methods you can use to access JSON objects from a nested JSON document. One method is to use recursion just like you access data from a nested array or tree data structure. Another method is to use loops. Let's look at some examples for accessing data a nested JSON document like below.

[{
	"id": 1,
	"name": "Max Adams",
	"born": "21 Oct 2001",
	"cars": [
		{"make": "Mercedes", "model": "GLS"	},
		{"make": "Audi", "model": "Q8" }
		],
	"favourite": { "colour": "Blue", "movie": "Toy Story" }
},
{
	"id": 2,
	"name": "Steven Miller",
	"born": "28 Jul 2004",
	"cars": [
		{"make": "Tesla", "model": "Model S"}
        ],
	"favourite": { "colour": "Red", "movie": "Mulan" }
},
{
	"id": 3,
	"name": "Daniel James",
	"born": "18 Dec 2005",
	"cars": [
		{"make": "Bugatti", "model": "Chiron"}
		],
	"favourite": { "colour": "Yellow", "movie": "Frozen", "toy": "Teddy" }
}]

Reading JSON

Consider that our example JSON is stored in a file named "persons.txt". Firstly read the contents of the text file into a string variable using the file_get_contents() function and then use json_decode() function to convert the JSON string to a PHP variable.

$filepath = './persons.txt';
$json_string = file_get_contents($filepath);
$json = json_decode($json_string, true);

Note that the second argument in the json_decode function is set to true so that the objects returned will be associative arrays.

For more details on parsing JSON in PHP, read How to parse JSON in PHP

Accessing objects inside a JSON array

To access the objects inside a JSON array, the simplest and easiest method is to use a foreach loop to iterate through the array elements and fetch the data that you need. For example, to print all the name and id numbers from our example JSON document:

foreach($json_array as $elem)  {
   echo($elem['id']. ", ".$elem['name'] );
   echo("<br/>");
}

This will output

2, Steven Miller
3, Daniel James

Accessing Nested objects inside a JSON array

The value of a JSON can be another JSON object. In our example JSON, there are three JSON objects each corresponding to the details about a person. For each person, there is a key named favourite whose value is another JSON object. You can access this inner JSON object just as you access a multidimensional associative array.

To print all the names and corresponding favourite colour.

foreach($json as $elem)  {
   echo( $elem['name']." - ".$elem['favourite']['colour'] );
   echo("<br/>");
}

Output:

Max Adams - Blue
Steven Miller - Red
Daniel James - Yellow

Accessing JSON arrays inside nested JSON

If you have an array inside a nested JSON object then use two foreach loops to access the inner array element.

To print all the names and corresponding cars.

foreach($json as $elem)  {
   echo( $elem['name']. " : " );
   foreach ($elem['cars'] as $car ) {
      echo($car['make']. ", ");
   }
   echo("<br/>");
}

Output

Max Adams : Mercedes, Audi,
Steven Miller : Tesla,
Daniel James : Bugatti,

Here is another example to print the number of cars each person has.

foreach($json as $elem)  {
   echo( $elem['name'].": ".count($elem['cars']));
   echo("<br/>");
}

Output:

Max Adams: 2
Steven Miller: 1
Daniel James: 1

Search a nested JSON by value

So far, we have seen how to access all objects at a particular level. Now we learn how to search a nested JSON for a specific value.

Our first example is to find all people who owns a 'Tesla' from our sample JSON.

$search_val = 'Tesla';
foreach($json as $elem) {
   foreach ( $elem['cars'] as $car) {
      if($car['make'] == $search_val) {
         echo($elem['name']);
         echo("<br/>");
      }
   }
}

Output:

Steven Miller

In the next example, we search for people who like the colour 'Blue'

$search_val = 'Blue';
foreach($json as $elem) {
   foreach ( $elem['favourite'] as $key => $val) {
      if ($key == 'colour' && $val == $search_val) {
         echo($elem['name']);
         echo("<br/>");
      }
   }
}

Output:

Max Adams

Search a nested JSON by key

In this next example we search for a key instead of a value. For example to find the people who has a favourite toy.

$search_key = 'toy';
foreach($json as $elem) {
   foreach ( $elem['favourite'] as $key => $val) {
      if ($key == $search_key) {
         echo($elem['name']." - ".$val);
      }
   }
}

Output:

Daniel James - Teddy

Recursively getting all keys and values

Now we look at the another method of accessing data from a nested JSON - Recursion. In this method we create a function which calls itself until a certain condition is met.

Let\'s start with a simple code snippet to print all the keys and values in our sample JSON document.

// Define function
function print_recursive($arr){

  foreach ($arr as $key => $val) {
    if (is_array($val)) {
      print_recursive($val);

    } else {
       echo("$key = $val <br/>");
    }
  }
return;
}

// Call function
print_recursive($json);

In the above code, the print_recursive function calls itself if the value is an array otherwise prints the key and value.

Output:

id = 1
name = Max Adams
born = 18 Dec 2005
make = Mercedes
model = GLS
make = Audi
model = Q8
colour = Blue
movie = Toy Story
id = 2
name = Steven Miller
...
...

Search by Key OR Value Recursively

You can recursively search for by key or value inside a nested JSON with a slight modification to the code above. All you need is to defina a function that takes two arguments - an array and a Key/Value. You then run the same recursion as before but you have another if condition to check for the specified key/value.

Here is an example to get all the car models

// Recursive function to search by key
function search_recursive_by_key($arr, $searchkey){

   foreach ($arr as $key => $val) {
      if (is_array($val)) {
         search_recursive_by_key($val, $searchkey);

      } else {
         if ($searchkey == $key) {
            echo("$key ||| $val <br/>");
         }
      }
   }
return;
}

// Call function with Key as second argument
search_recursive_by_key($json, 'model');

Output:

model ||| GLS
model ||| Q8
model ||| Model S
model ||| Chiron

Similarly, you can search for a value. For example, to find all people born on a particular date.

// Recursive function to search by value
function search_recursive_by_value($arr, $searchval){

   foreach ($arr as $key => $val) {
      if (is_array($val)) {
         search_recursive_by_value($val, $searchval);
         } else {
         if ($searchval == $val) {
            echo("$key :: $val <br/>");
         }
      }
   }
return;
}
// Call function with value to search as second argument
search_recursive_by_value($json, '18 Dec 2005');

Output:

born :: 18 Dec 2005

Search by Key AND Value Recursively

In the previous examples, you searched for a key or value and echo that key-value pair when found. But, most of the time you might want to search for a key or value and echo its Parent node or a different key-value pair. For example, you want to search for a date and echo the name of the person who was born on that date. Or, search for a car and get the people who has that car. Here is the function to do that.

// Recursive function to search by Key and Value
function search_recursive_key_value($arr, $searchkey, $searchval, $result=null){

   foreach ($arr as $key => $val) {
      if (is_array($val)) {
           search_recursive_key_value($val, $searchkey, $searchval,  $result);

      } else {
           if ($key == $searchkey) {
              $result = $val;
           }

           if ($searchval == $val) {
              echo("$result => $val <br/>");
           }
      }
   }
return;
}
// Call function with a key to output and value to search
search_recursive_key_value($json, 'name', '28 Jul 2004');
search_recursive_key_value($json, 'make', 'Audi');

Output:

Steven Miller => 28 Jul 2004
Max Adams => Audi

PHP also provides several built-in array functions to get data from a nested JSON, once JSON string is decoded to a PHP object. We will discuss this in the next post.


Post a comment

Comments

EndSS | November 5, 2020 8:04 PM |

What would an insert in the POST method look like with nested JSON?

SmallCorrection | May 8, 2020 11:06 AM |

One small correction, part "Recursively getting all keys and values".
In foreach loop instead of $val=search_recursive($val), need to be $val=print_recursive($val) I suppose.

Admin | May 10, 2020 12:20 PM |

Thanks for pointing it out, article updated now.