Categories
json php

How can I parse a JSON file with PHP? [duplicate]

478

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.

11

  • 62

    You’re on the right track. Look up the syntax for foreach (you should get keys and values). Don’t give up yet!

    Dec 3, 2010 at 8:12

  • 11

    @Stefan Mai: foreach($variable as $key => $val) should be what you want 🙂

    – Bojangles

    Dec 3, 2010 at 8:15

  • 6

    @JamWaffles Haha, thanks. I was hoping OP could get some experience looking it up. Upvotes because it’s really all he/she needs.

    Dec 3, 2010 at 8:16

  • Side note: I suggest you configure your PHP setup to display all kind of error messages, including notices

    Dec 3, 2010 at 8: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 3, 2010 at 10:43

354

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

7

  • 13

    Does this approach offer any special advantage over good old foreach?

    Dec 3, 2010 at 8: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 3, 2010 at 8:39


  • alright, I hadn’t considered that nesting level was variable. In such case, this is cleaner than a recursive function.

    Dec 3, 2010 at 9: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.

    Aug 29, 2015 at 23:51

  • @Jesse php.net/manual/en/class.recursiveiteratoriterator.php would allow you to detect the depth.

    – Gordon

    Aug 30, 2015 at 7:08

162

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'];
}

?>

4

  • 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, 2015 at 9: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, 2019 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, 2021 at 4: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, 2021 at 14:11

60

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;

4

  • 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, 2015 at 1:26

  • 9

    BOM = byte order mark.

    – swift

    Mar 2, 2015 at 9:35

  • 3

    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 2, 2015 at 9:41

  • This post does not attempt to answer the posted question

    Mar 28, 2019 at 12:02