user570494
user570494

Reputation: 567

json_decode returns NULL for a string variable

I met a really weird problem on json_decode, with this code:

$url="http://localhost:8983/solr/db/select?wt=json&rows=1&q=94305";
$string=file_get_contents($url);
echo $string; echo '<br><br>';
$json=json_decode($string);
var_dump($json);

I got the following result:

{"responseHeader":{"status":0,"QTime":0,"params":{"q":"94305","wt":"json","rows":"1"}},"response":{"numFound":165,"start":0,"docs":[{"price":"","tags":"ATMs","phone_n":"","location":"37.42409897,-122.1709976 ","store":"Discover ATM","store_id":"478602","state":"CA","latitude":"37.42409897","address":"459 LAGUNITA","zipcode_n":"94305","longitude":"-122.1709976\r","url":"Discover_ATM_459_LAGUNITA_Stanford_CA_94305","city":"Stanford","category":"ATMs","text":["","CA","459 LAGUNITA","94305","Stanford"],"spell":["Discover ATM"]}]}}

NULL 

It seems that I cannot json_decode this string. However, when I do like this (copy the output of the string above and put it to $string directly):

$string='{"responseHeader":{"status":0,"QTime":0,"params":{"q":"94305","wt":"json","rows":"1"}},"response":{"numFound":165,"start":0,"docs":[{"price":"","tags":"ATMs","phone_n":"","location":"37.42409897,-122.1709976 ","store":"Discover ATM","store_id":"478602","state":"CA","latitude":"37.42409897","address":"459 LAGUNITA","zipcode_n":"94305","longitude":"-122.1709976\r","url":"Discover_ATM_459_LAGUNITA_Stanford_CA_94305","city":"Stanford","category":"ATMs","text":["","CA","459 LAGUNITA","94305","Stanford"],"spell":["Discover ATM"]}]}}';
$json=json_decode($string);
var_dump($json);

json_decode works. Why json_decode get NULL at the first part while works properly here?

Upvotes: 7

Views: 4038

Answers (2)

Ja͢ck
Ja͢ck

Reputation: 173662

Your code looks okay, so let's take one step closer and investigate what $output really is. It helps to choose a representation that can handle ASCII ranges that you can't see.

echo bin2hex($output);

That will give a huge string, but you'll be mostly interested in the front and back of the string.

If that seems kosher, you can create an in-between representation:

echo preg_replace('@[\x00-\x1f\x7f-\xff]@e', '" (0x" . dechex(ord("\\0")) . ") "', $output);

It replaces any character in the lower or higher ASCII range with a hexadecimal representation, making it somewhat easier to spot them :)

Update

From your investigation based on the above, your string seems to contain a carriage return - \r - somewhere in the middle.

"CA","latitude":"37.42409897","
                            ^

You can remove those with a preg_replace() if it can't be solved in another way.

preg_replace("/\r(?!\n)/", '', $output);

That removes any \r not followed by a \n.

Upvotes: 4

Navneet Singh
Navneet Singh

Reputation: 1198

There may be some NULL bytes in the string

Remove it using

$string = trim($string, "\x0");
$json=json_decode($string);
var_dump($json);

Change the Content type to json on this page http://localhost:8983/solr/db/select?wt=json&rows=1&q=94305

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

Remove BOM (Byte Order mark)

if (substr($string, 0,3) == pack("CCC",0xef,0xbb,0xbf)) { 
$string = substr($string, 3); 
}

Check if error occurred in parsing the json data

   $json_errors = array(
         JSON_ERROR_NONE => 'No error has occurred',
         JSON_ERROR_DEPTH => 'The maximum stack depth has been exceeded',
         JSON_ERROR_CTRL_CHAR => 'Control character error, possibly incorrectly encoded',
         JSON_ERROR_SYNTAX => 'Syntax error',
        );
        echo 'Last error : ',

 $json_errors[json_last_error()], PHP_EOL, PHP_EOL;

Upvotes: 3

Related Questions