Why has json_decode started returning NULL?

Hi all

I have a PHP import script I built about a year ago, been working great! Though all of a sudden, my json_decode has started returning a NULL value resulting in:

Warning: Invalid argument supplied for foreach() in…

PHP Version 5.3.29

$json = json_decode(file_get_contents('events.json'), true);
foreach ($json as $row) {
...

var_dump($json); // Equals NULL

Events.json - Example

[
        {
          "TRANSP": "OPAQUE",
          "DTEND": "20160601T020000Z",
          "DTSTAMP": "20160524T185925Z",
          "LOCATION": "Big Warehouse",
          "DESCRIPTION": "",
          "SEQUENCE": "26533666",
          "SUMMARY": "Tickets OUT NOW!",
          "DTSTART": "20160531T210000Z",
          "CREATED": "20150722T163139Z"
        },
        {
          "TRANSP": "OPAQUE",
          "DTEND": "20160601T020000Z",
          "DTSTAMP": "20160524T185925Z",
          "LOCATION": "Small Warehouse",
          "DESCRIPTION": "",
          "SEQUENCE": "26533666",
          "SUMMARY": "Tickets SOLD OUT!",
          "DTSTART": "20160531T210000Z",
          "CREATED": "20150722T163139Z"
        }
]

Tired everything - Just can’t figure out why this has suddenly stopped working?

The only thing I can think of, might be caused by the DESCRIPTION which has random data/characters that are not converting.

Any ideas?

Thanks, Barry

No. Empty fields wouldn’t really cause that error. It could be the file_get_content. The Json file should not return anything on render if it was due to an empty field. I assume it is because of file_get_content. Usually, if it was due to empty fields, it would complain and say something like undefined index or something like that. Fields are different from file. The only thing that comes to mind is that the json_decode line fails.

Because you aren’t checking for the JSON errors

function jsonDecode($json, $assoc = false)
{
    $ret = json_decode($json, $assoc);
    if ($error = json_last_error())
    {
        $errorReference = [
            JSON_ERROR_DEPTH => 'The maximum stack depth has been exceeded.',
            JSON_ERROR_STATE_MISMATCH => 'Invalid or malformed JSON.',
            JSON_ERROR_CTRL_CHAR => 'Control character error, possibly incorrectly encoded.',
            JSON_ERROR_SYNTAX => 'Syntax error.',
            JSON_ERROR_UTF8 => 'Malformed UTF-8 characters, possibly incorrectly encoded.',
            JSON_ERROR_RECURSION => 'One or more recursive references in the value to be encoded.',
            JSON_ERROR_INF_OR_NAN => 'One or more NAN or INF values in the value to be encoded.',
            JSON_ERROR_UNSUPPORTED_TYPE => 'A value of a type that cannot be encoded was given.',
        ];
        $errStr = isset($errorReference[$error]) ? $errorReference[$error] : "Unknown error ($error)";
        throw new \Exception("JSON decode error ($error): $errStr");
    }
    return $ret;
}

The only thing that comes to mind is that the json_decode line fails.

Yes this is the problem, hence var_dump($json); // Equals NULL

Sorry, the description is not empty, I’ve removed the content to shorten things down for viewing. Every description has a good amount of data which comes from a third party, and inside this data are a lot of special characters mixed within the copy. As mentioned, everything has been working for many months, only recently it started returning a NULL value. And because I have started seeing new characters, I thought maybe this could be causing the issue, as I’ve tried everything else.

Any suggestions?

Barry

Parse error: syntax error, unexpected ‘[’ in public_html/… on line 64

Line 64. $errorReference = [

PHP 5.3

Thanks, Barry

Update: I needed to use array() in place of due to earlier php version.

Everything ran ok, no error but giving me the same problem:

Warning: Invalid argument supplied for foreach() in

The JSON is well formed as I’ve tested this already. This is why am so stumped, one minute everything is working, the next NULL.

??

Barry

I suspect file_get_content. It usually has problems grabbing data from other sources. Try using cURL. If the problem persists, then it’s the Json file. But I honestly don’t think that is the issue. If the problem is within the Json file, the file would never render as I have said above. Make sure the Json file doesn’t contain double quotes. You have to escape double quotes because Json uses double quotes to wrap its contents in.

The json file is what you see in #1 but on a much bigger scale. The files data is from a third party though I build and compile the json file myself.

And just to reiterate, everything has worked for months, all of a sudden its stopped working.

Anyhow, I’ll have to see if I can find another solution or figure out what’s causing this.

Thanks anyway.

Barry

Surely a simple matter to check, once and for all, whether it’s file_get_contents() causing the issue. Change this

$json = json_decode(file_get_contents('events.json'), true);

for this

$indata = file_get_contents('events.json');
// check here whether you got what you wanted
$json = json_decode($indata, true);
// and check again here.

Merging multiple statements where possible is great, but it makes it marginally more difficult when things go wrong. Has the json file suddenly hit a size limit, for example?

Has the json file suddenly hit a size limit, for example?

That’s a very good call! And something I did think about.
The JSON file is increasing by about 20-60 entries a fortnight.

I’ll post back shortly once I check your other suggests above.

Thanks,
Barry

Thanks @droopsnoot - I tried:

$indata = file_get_contents('events.json');
var_dump($indata);

$json = json_decode($indata, true);
var_dump($json);

foreach ($json as $row) {

string(0) “” NULL Warning: Invalid argument supplied for foreach() in…

But still nothing.

I also reduced the events.json to two items, same error and result.


I’ve also noticed I recently converted a lot of my DB tables to InnoDB, but my events table is still MyISAM, maybe this is what’s causing the error? As you say, to large.

How could I check, what other checks could I do?

Update: After making a clone and switching db engines

MyISAM = 830
became
InnoDB = 783

But still…

Warning: Invalid argument supplied for foreach() in /

Barry

As I have said, use cURL to see if it works. I am pretty convinced that file_get_content is the issue. From my experience, I had a working live Json file. I then tried to use file_get_content on the working file, but it could never work. Kept getting NULL on request. Do you see where our experiences are similar? I then switched to using cURL because the host I was on said that file_get_content sometimes fails on their host. So I did switch to cURL and my Json file still works til this day.

I am pretty sure we have the same issue because I had it all working with file_get_content until they migrated to a different server. That’s when it started acting up.

You should also die() before the foreach too. It makes no sense to debug the line that it’s complaining about if the Json file returns NULL.

I can relate to that, sounds exactly my situation :slight_smile:

I’ll give this a try and see what happens @spaceshiptrooper
I was just a little reluctant to try, telling myself it was already working - how can this be the problem ha

Ok, doing quick google as never used cURL before.

Post back shortly with result.

Thanks, Barry

Was feeling so hopefully :neutral_face:

It doesn’t work.

I tried below quick snippet I found:

$url = 'events.json';

$rCURL = curl_init();

curl_setopt($rCURL, CURLOPT_URL, $url);
curl_setopt($rCURL, CURLOPT_HEADER, 0);
curl_setopt($rCURL, CURLOPT_RETURNTRANSFER, 1);

$aData = curl_exec($rCURL);

curl_close($rCURL);

$json = json_decode ( $aData, true );
var_dump($json);
die();

NULL

Any thanks after adding die() - runs a lot faster!

Any more ideas?
And does the code above look right?

Thanks, Barry

Exactly where is events.json, on the same server or elsewhere? If it’s on the same server, would CURL be the way to do it? I thought that was only for accessing a file on a HTTP server, i.e. pretending to be a browser of some sort.

Yes it’s on the same server.
Not familiar with CURL. Though as the further test shows, this is not the fix.

I’ve done it the same way for nearly going on a year - never had a problem

http://www.example.com/json/events.json

?

Barry

What headers are being sent from the file outputting the JSON? “Content-type: application/json”?

I’m not sure, how do I check?

Also, I just ran the below from inside the import file where the code above is placed:

$jsons = '[{
          "NAME": "Barry",
          "LANG": "SQL"
        },{
          "NAME": "Barry2",
          "LANG": "PHP"
        }]';

$obj = json_decode($jsons, true);
var_dump($obj);

Which works and shows:

array(2) { [0]=> array(2) { ["NAME"]=> string(5) "Barry" ["LANG"]=> string(3) "SQL" } [1]=> array(2) { ["NAME"]=> string(6) "Barry2" ["LANG"]=> string(3) "PHP" } }

Barry

AFAIK, the default type for .php files is text/html
What l do when I want a PHP file to output different is use the header() function.

Not sure.

I added:
header('Content-type:application/json;charset=utf-8');

This just turns my errors into json text.
As mentioned, everything has always been ok, never needed to mess with headers.

Barry

Hmmm, l’m running out of ideas. Both files are the same domain so it’s not a allow_url configure thing. The code colshrapnel posted isn’t giving any errors so it’s not one of the more common problems. I can’t think of what else it might be.