491

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.

Cedric Ipkiss
  • 5,662
  • 2
  • 43
  • 72
John Doe
  • 9,843
  • 13
  • 42
  • 73
  • 65
    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 Dec 03 '10 at 08:12
  • 11
    @Stefan Mai: `foreach($variable as $key => $val)` should be what you want :-) – Bojangles Dec 03 '10 at 08:15
  • Side note: I suggest you configure your PHP setup to display all kind of error messages, including `notices` – Álvaro González Dec 03 '10 at 08:39
  • 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 Dec 03 '10 at 10:43
  • X-Ref: [How do I extract data from JSON with PHP?](//stackoverflow.com/q/29308898) (for more finicky array traversion). – mario Feb 04 '18 at 11:12
  • A bit off-topic but you need to make sure that `allow_url_fopen` is set to `1` for this to work on every server. If you're using a third party server it might not work. Cheers! – Valentin Genev Nov 02 '20 at 16:16
  • Have in mind that json decode has trouble with special characters. You can fix it by appending the options as described here to have a full utf8 character save json_decode https://stackoverflow.com/a/39364497/2223756 – Gkiokan Jul 07 '22 at 15:38

16 Answers16

355

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

xpy
  • 5,481
  • 3
  • 29
  • 48
Gordon
  • 312,688
  • 75
  • 539
  • 559
  • 13
    Does this approach offer any special advantage over good old foreach? – Álvaro González Dec 03 '10 at 08:32
  • 20
    @Á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 Dec 03 '10 at 08:39
  • alright, I hadn't considered that nesting level was variable. In such case, this is cleaner than a recursive function. – Álvaro González Dec 03 '10 at 09:04
  • 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 Aug 29 '15 at 23:51
  • @Jesse http://php.net/manual/en/class.recursiveiteratoriterator.php would allow you to detect the depth. – Gordon Aug 30 '15 at 07:08
  • @Gordon Thanks for the link. So the example becomes like: `echo $jsonIterator->getDepth() . "- $key:\n";` and `echo $jsonIterator->getDepth() . "- $key => $val\n";` – Jesse Chisholm May 10 '16 at 13:12
  • so in this loop if we have to change the data then how it will be , so that change could be write back to file or database – user889030 Nov 13 '18 at 12:47
165

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");
if ($string === false) {
    // deal with error...
}

$json_a = json_decode($string, true);
if ($json_a === null) {
    // deal with error...
}

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

?>
Flimm
  • 136,138
  • 45
  • 251
  • 267
BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
  • 7
    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). – eQ19 Apr 16 '15 at 09:55
  • 2
    @Chetabahana That's actually not correct. If you use a relative path like `test.json`, then the path is evaluated relative to the current directory, not necessarily where the PHP script is. On bash, you can discover the current directory by typing `pwd`. – Flimm Aug 28 '19 at 13:22
  • @Flimm If the PHP and JSON and execution occur on the same directory, there is no need to specify the absolute path of JSON file. Correct? – Nguai al Jan 21 '21 at 04:33
  • 1
    @Nguaial That depends on what the current working directory is. For example, let's say you have a PHP file `/home/user/project/test.php` and a JSON file `/home/user/project/json.json`. If your current working is `/home/user`, then to run the PHP file you would type `php project/test.php`. In this case, the PHP file would need to refer to the JSON file as `project/test.json` as relative paths are relative to the current working directory, not necessarily to the parent directory of the PHP file. – Flimm Jan 22 '21 at 14:11
62

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;
swift
  • 1,108
  • 7
  • 9
  • 7
    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 Feb 12 '15 at 01:26
  • 9
    BOM = byte order mark. – swift Mar 02 '15 at 09:35
  • 3
    http://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 Mar 02 '15 at 09:41
  • This post does not attempt to answer the posted question – mickmackusa Mar 28 '19 at 12:02
42

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;
}
?>
Thariama
  • 50,002
  • 13
  • 138
  • 166
  • 6
    _Try This_ answers are low value on StackOverflow because they do very little to educate the OP and future researchers. If you are going to leave this answer on the page, please explain how your answer works and why it is advisable. – mickmackusa Sep 01 '18 at 03:49
  • As proven by BoltClock's answer, this answer is incorrect for the question's sample data. – mickmackusa Mar 28 '19 at 11:19
  • how does it iterate the nested multi dim array – Muhammad Omer Aslam Sep 08 '19 at 20:41
20

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.

David
  • 1,227
  • 12
  • 23
  • You are right for pointing out the array thing. – Stephen Adelakun Aug 23 '16 at 08:40
  • 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 Aug 23 '16 at 08:51
  • "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 Aug 24 '16 at 19:25
  • This post fails to answer the question of how to parse a json string and access subarray elements from unknown first level keys. This is Not An Answer and should be a comment under the question. It almost looks like you are recommending that the file should be read, then mutated by string functions to suit your preference. I don't get it. – mickmackusa Mar 28 '19 at 11:26
  • No, I'm pointing out the structure of the file is wrong for the purpose he is reading it. And therefore it does answer the question. And it indeed seems you don't get it, because I said nothing about string functions. That is just silly. – David Apr 02 '19 at 11:26
16

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);
    }
Dane Brouwer
  • 2,827
  • 1
  • 22
  • 30
vivek
  • 354
  • 2
  • 9
  • 11
    _Try This_ answers are low value on StackOverflow because they do very little to educate the OP and future researchers. If you are going to leave this answer on the page, please explain how your answer works and why it is advisable. – mickmackusa Sep 01 '18 at 03:46
  • The OP asks for parsing data from JSON file, not JSON from variable inside your code. – ibnɘꟻ Apr 05 '21 at 03:35
9

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 />';
        }
    }
}
Indrajeet Singh
  • 2,958
  • 25
  • 25
  • 2
    _Try This_ answers are low value on StackOverflow because they do very little to educate the OP and future researchers. If you are going to leave this answer on the page, please explain how your answer works and why it is advisable. – mickmackusa Sep 01 '18 at 03:46
9

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
Diptesh Atha
  • 851
  • 8
  • 18
  • or can say `$data = json_decode(file_get_contents("db.json"), true);` for first line – Danish Aug 25 '18 at 02:33
  • 3
    Code-only answers are low value on StackOverflow because they do very little to educate the OP and future researchers. If you are going to leave this answer on the page, please explain how your answer works and why it is advisable. – mickmackusa Sep 01 '18 at 03:46
  • 1
    It makes no sense to call `array_keys()` here when the following `foreach()` loop can provide the data all by itself. I don't think I agree with "more standard", and I can think of a few better variable names versus `$val`. – mickmackusa Mar 28 '19 at 11:29
8

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
        }
    }
}
Alex
  • 64,178
  • 48
  • 151
  • 180
8
<?php
$json = '{
    "response": {
        "data": [{"identifier": "Be Soft Drinker, Inc.", "entityName": "BusinessPartner"}],
        "status": 0,
        "totalRows": 83,
        "startRow": 0,
        "endRow": 82
    }
}';
$json = json_decode($json, true);
//echo '<pre>'; print_r($json); exit;
echo $json['response']['data'][0]['identifier'];
$json['response']['data'][0]['entityName']
echo $json['response']['status']; 
echo $json['response']['totalRows']; 
echo $json['response']['startRow']; 
echo $json['response']['endRow']; 

?>
sunny bhadania
  • 423
  • 3
  • 5
  • 4
    Code-only answers are low value on StackOverflow because they do very little to educate the OP and future researchers. If you are going to leave this answer on the page, please explain how your answer works and why it is advisable. – mickmackusa Sep 01 '18 at 03:47
  • 1
    Rather than ignoring the sample data provided by the OP, please attempt to answer the question in a way that will immediately and directly relate to the posted question. – mickmackusa Mar 28 '19 at 12:06
3

Try it:

foreach ($json_a as $key => $value)
 {
   echo $key, ' : ';
   foreach($value as $v)
   {
       echo $v."  ";
   }
}
Hamender
  • 39
  • 3
  • 2
    _Try This_ answers are low value on StackOverflow because they do very little to educate the OP and future researchers. If you are going to leave this answer on the page, please explain how your answer works and why it is advisable. – mickmackusa Sep 01 '18 at 03:47
1

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";
     }
?>
Daniel Blanco
  • 509
  • 7
  • 14
1
$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>";
    }

}
  • 6
    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 Nov 19 '14 at 05:37
0

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;

        }

    }
The Bumpaster
  • 944
  • 7
  • 20
-1

I am using below code for converting json to array in PHP, If JSON is valid then json_decode() works well, and will return an array, But in case of malformed JSON It will return NULL,

<?php
function jsonDecode1($json){
    $arr = json_decode($json, true);
    return $arr;
}

// In case of malformed JSON, it will return NULL
var_dump( jsonDecode1($json) );
?>

If in case of malformed JSON, you are expecting only array, then you can use this function,

<?php
function jsonDecode2($json){
    $arr = (array) json_decode($json, true);
    return $arr;
}

// In case of malformed JSON, it will return an empty array()
var_dump( jsonDecode2($json) );
?>

If in case of malformed JSON, you want to stop code execution, then you can use this function,

<?php
function jsonDecode3($json){
    $arr = (array) json_decode($json, true);

    if(empty(json_last_error())){
        return $arr;
    }
    else{
        throw new ErrorException( json_last_error_msg() );
    }
}

// In case of malformed JSON, Fatal error will be generated
var_dump( jsonDecode3($json) );
?>
HarisH Sharma
  • 1,101
  • 1
  • 11
  • 38
  • `empty()` is unnecessary overhead. Just use `!json_last_error()`. Furthermore, this fails to answer the question asked by the OP. It is not "How to cast values as arrays" and it is not "how to check for JSON errors". I am flagging this post as Not An Answer. – mickmackusa Mar 28 '19 at 11:55
  • But no one addressed the case for if json is malformed, so only json_decode() is not enough, should check for valid json also, its your thinking man, marked if u want, I am not here to earn points, as a developer only solution is not enough, pros n cons also, – HarisH Sharma Mar 28 '19 at 17:04
  • Every answer is expected to answer the exact question asked. If every answer bled out to associated subject matter, Stackoverflow pages would be much harder for researchers to find the solutions that they are actually hunting. Sometimes I pack my answers with error checking (commonly with my mysql answers) because it is a reasonable accompaniment to a correct solution. I would never purely post error instructions on a "How do I CROSS JOIN" question, for example, because that would not answer the posted question. Do you see now why your post is inappropriate? It has lost sight of the question. – mickmackusa Mar 28 '19 at 20:06
  • You have posted the correct answer to the wrong question. Better places may include: https://stackoverflow.com/q/2348152/2943403 or https://stackoverflow.com/q/6041741/2943403 or https://stackoverflow.com/q/5970270/2943403 and many, many more. – mickmackusa Mar 28 '19 at 20:14
-1

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
Elmo
  • 6,409
  • 16
  • 72
  • 140
muneeb
  • 17
  • 1
  • 1
    _Do Like This_ answers are low value on StackOverflow because they do very little to educate the OP and future researchers. If you are going to leave this answer on the page, please explain how your answer works and why it is advisable. – mickmackusa Sep 01 '18 at 03:49
  • This answer appears to misunderstand the question. The OP doesn't know the "name" keys in advance, so they cannot be hardcoded. This answer is incorrect. – mickmackusa Mar 28 '19 at 11:57