I tried to parse a JSON file using PHP. But I am stuck now.

This is the content of my JSON file:

{
    "John": {
        "status":"Wait"
    },
    "Jennifer": {
        "status":"Active"
    },
    "James": {
        "status":"Active",
        "age":56,
        "count":10,
        "progress":0.0029857,
        "bad":0
    }
}

And this is what I have tried so far:

<?php

$string = file_get_contents("/home/michael/test.json");
$json_a = json_decode($string, true);

echo $json_a['John'][status];
echo $json_a['Jennifer'][status];

But because I don't know the names (like 'John', 'Jennifer') and all available keys and values (like 'age', 'count') beforehand, I think I need to create some foreach loop.

I would appreciate an example for this.

30 upvote
  flag
You're on the right track. Look up the syntax for foreach (you should get keys and values). Don't give up yet! – Stefan Mai
8 upvote
  flag
@Stefan Mai: foreach($variable as $key => $val) should be what you want :-) – Bojangles
4 upvote
  flag
@JamWaffles Haha, thanks. I was hoping OP could get some experience looking it up. Upvotes because it's really all he/she needs. – Stefan Mai
upvote
  flag
Side note: I suggest you configure your PHP setup to display all kind of error messages, including notices – Álvaro González
upvote
  flag
Can you elaborate on what you're trying to get out of "parsing" the JSON: i.e. what task are you trying to accomplish with your code (like: "output all statuses", "find names where status is xyz", "find all information for xyz")? – salathe
upvote
  flag
(Windows Notepad issue) Please, consult this, I shared the problem too and it fixed it: //allinonescript.com/questions/10290849/… – Félix
upvote
  flag
great that nobody got nazi about redirecting this question to codereview.. lucky you – juggernaut1996
upvote
  flag
@juggernaut1996 Code Review didn't even exist when this question was asked back in 2010. – 202_accepted

14 Answers 11

Try

<?php
$string = file_get_contents("/home/michael/test.json");
$json_a=json_decode($string,true);

foreach ($json_a as $key => $value){
  echo  $key . ':' . $value;
}
?>

Loop through the JSON with a foreach loop as key-value pairs. Do type-checking to determine if more looping needs to be done.

foreach($json_a as $key => $value) {
    echo $key;
    if (gettype($value) == "object") {
        foreach ($value as $key => $value) {
          # and so on
        }
    }
}
upvote
  flag
Or better yet, know what the structure is beforehand. – Ignacio Vazquez-Abrams

I can't believe so many people are posting answers without reading the JSON properly.

If you foreach iterate $json_a alone, you have an object of objects. Even if you pass in true as the second parameter, you have a two-dimensional array. If you're looping through the first dimension you can't just echo the second dimension like that. So this is wrong:

foreach ($json_a as $k => $v) {
   echo $k, ' : ', $v;
}

To echo the statuses of each person, try this:

<?php

$string = file_get_contents("/home/michael/test.json");
$json_a = json_decode($string, true);

foreach ($json_a as $person_name => $person_a) {
    echo $person_a['status'];
}

?>
1 upvote
  flag
If the php and json files are in the same dir, we can read json with file_get_contents("test.json"); (No need to put the path). – hyip
up vote 255 down vote accepted

To iterate over a multidimensional array, you can use RecursiveArrayIterator

$jsonIterator = new RecursiveIteratorIterator(
    new RecursiveArrayIterator(json_decode($json, TRUE)),
    RecursiveIteratorIterator::SELF_FIRST);

foreach ($jsonIterator as $key => $val) {
    if(is_array($val)) {
        echo "$key:\n";
    } else {
        echo "$key => $val\n";
    }
}

Output:

John:
status => Wait
Jennifer:
status => Active
James:
status => Active
age => 56
count => 10
progress => 0.0029857
bad => 0

run on codepad

4 upvote
  flag
Does this approach offer any special advantage over good old foreach? – Álvaro González
9 upvote
  flag
@Álvaro obviously. With foreach you can only recurse one level of depth. With the above approach you can recurse over a multilevel array. Plus, the entire thing is capsuled in OOP, so you have better reuse and you can easily mock it in UnitTests plus you can stack Iterators with other iterators doing different things, like limiting, caching, filtering and so on.. in addition to any custom iterators you might want to create. – Gordon
upvote
  flag
alright, I hadn't considered that nesting level was variable. In such case, this is cleaner than a recursive function. – Álvaro González
upvote
  flag
This style parsing, though, leaves some ambiguity. For example {'John':{'status':'waiting', 'Mary':{'status','nested'}}, 'Suzy':{'status:'waiting'} } is indistinguishable from {'John':{'status':'waiting'}, 'Mary':{'status','nested'}, 'Suzy':{'status:'waiting'} }. That Mary is a structural child of John is lost. – Jesse Chisholm
upvote
  flag
@Jesse php.net/manual/en/class.recursiveiteratoriterator.php would allow you to detect the depth. – Gordon
upvote
  flag
@Gordon Thanks for the link. So the example becomes like: echo $jsonIterator->getDepth() . "- $key:\n"; and echo $jsonIterator->getDepth() . "- $key => $val\n"; – Jesse Chisholm

You have to give like this:

echo  $json_a['John']['status']; 

echo "<>"

echo  $json_a['Jennifer']['status'];

br inside <>

Which gives the result :

wait
active

Try it:

foreach ($json_a as $key => $value)
 {
   echo $key, ' : ';
   foreach($value as $v)
   {
       echo $v."  ";
   }
}

Try:

$string = file_get_contents("/home/michael/test.json");
$json = json_decode($string, true);

foreach ($json as $key => $value) {
    if (!is_array($value)) {
        echo $key . '=>' . $value . '<br />';
    } else {
        foreach ($value as $key => $val) {
            echo $key . '=>' . $val . '<br />';
        }
    }
}

When you decode a json string, you will get an object. not an array. So the best way to see the structure you are getting, is to make a var_dump of the decode. (this var_dump can help you understand the structure, mainly in complex cases).

<?php
     $json = file_get_contents('/home/michael/test.json');
     $json_a = json_decode($json);
     var_dump($json_a); // just to see the structure. It will help you for future cases
     echo "\n";
     foreach($json_a as $row){
         echo $row->status;
         echo "\n";
     }
?>
$json_a = json_decode($string, TRUE);
$json_o = json_decode($string);



foreach($json_a as $person => $value)
{
    foreach($value as $key => $personal)
    {
        echo $person. " with ".$key . " is ".$personal;
        echo "<br>";
    }

}
3 upvote
  flag
Hiya, this may well solve the problem... but it'd be good if you could edit your answer and provide a little more explanation about how and why it works :) Don't forget - there are heaps of newbies on Stack overflow, and they could learn a thing or two from your expertise - what's obvious to you might not be so to them. – Taryn East

The most elegant solution:

$shipments = json_decode(file_get_contents("shipments.js"), true);
print_r($shipments);

Remember that the json-file has to be encoded in UTF-8 without BOM. If the file has BOM, then json_decode will return NULL.

Alternatively:

$shipments = json_encode(json_decode(file_get_contents("shipments.js"), true));
echo $shipments;
upvote
  flag
Pretty awesome, but the whole Bill Of Materials (BOM) thing has me totally confused. er... what are you talking about? Am I the only guy miffed at the used of mystery unexplained abbreviations? Okay to use abbreviations, but please explain When First Used (WFU)... thanks. – zipzit
3 upvote
  flag
BOM = byte order mark. – swift
1 upvote
  flag
en.wikipedia.org/wiki/Byte_order_mark Typical gotcha if you're working with json on both mac and pc, since they use different default text formats. – swift

It's completely beyond me that no one pointed out that your begining "tags" are wrong. You're creating an object with {}, while you could create an array with [].

[ // <-- Note that I changed this
    {
        "name" : "john", // And moved the name here.
        "status":"Wait"
    },
    {
        "name" : "Jennifer",
        "status":"Active"
    },
    {
        "name" : "James",
        "status":"Active",
        "age":56,
        "count":10,
        "progress":0.0029857,
        "bad":0
    }
] // <-- And this.

With this change, the json will be parsed as an array instead of an object. And with that array, you can do whatever you want, like loops etc.

upvote
  flag
You are right for pointing out the array thing. – Stephen Adelakun
upvote
  flag
Oh mine. I should add that you seem to have removed the key in the OP's json while converting to array. So the OP is right. – Stephen Adelakun
upvote
  flag
"But because I don't know the names (like John, Jennifer) and all available keys". He seems to not know the keys, so the only way to traverse the collection is a loop. This kind of tells me he does not direct access to the values by key. – David

The quickest way to echo all json values is using loop in loop, the first loop is going to get all the objects and the second one the values...

foreach($data as $object) {

        foreach($object as $value) {

            echo $value;

        }

    }

More standard answer:

$jsondata = file_get_contents(PATH_TO_JSON_FILE."/jsonfile.json");

$array = json_decode($jsondata,true);

foreach($array as $k=>$val):
    echo '<b>Name: '.$k.'</b></br>';
    $keys = array_keys($val);
    foreach($keys as $key):
        echo '&nbsp;'.ucfirst($key).' = '.$val[$key].'</br>';
    endforeach;
endforeach;

And the output is:

Name: John
 Status = Wait
Name: Jennifer
 Status = Active
Name: James
 Status = Active
 Age = 56
 Count = 10
 Progress = 0.0029857
 Bad = 0

Try This

$json_data = '{
"John": {
    "status":"Wait"
},
"Jennifer": {
    "status":"Active"
},
"James": {
    "status":"Active",
    "age":56,
    "count":10,
    "progress":0.0029857,
    "bad":0
  }
 }';

 $decode_data = json_decode($json_data);
foreach($decode_data as $key=>$value){

        print_r($value);
}

Not the answer you're looking for? Browse other questions tagged or ask your own question.