7

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?

6
  • 3
    Check for BOM (Byte order mark) in the string Commented Dec 19, 2012 at 8:00
  • Perhaps the response contains a newline at the end? Commented Dec 19, 2012 at 8:00
  • Try print_r($string) instead of echo $string Commented Dec 19, 2012 at 8:01
  • First check if error occurred in parsing the json data with the code i posted in the answer. Where is the data coming from exactly? Commented Dec 19, 2012 at 8:02
  • I already checked the BOM before I post this. print_r prints the exact same thing with echo. Commented Dec 19, 2012 at 8:13

2 Answers 2

4

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.

Sign up to request clarification or add additional context in comments.

4 Comments

There is some difference in the middle: 370d222c vs 3720222c
@user570494 Not sure why you have a carriage return in the middle there, but it might be causing issues ... I've updated my answer with a hackish solution .. it's better to know why solr gives you that result in the first place.
preg_replace("/\r(?!\n)/", '', $output); works! Thank you so much!
@user570494 Seriously weird! :) I would do some more thorough research on why solr would give you those results ;-)
3

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;

8 Comments

Tried $string = trim($string, "\x0");, no luck.
I tried it on another server, it got " Last error : Syntax error "
The content type is set as json.
No luck with removing BOM. (there is no BOM).
then the last thing you can do is by matching the bin2hex of received json string with bin2hex of actual json string , Check this function
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.