6

I'm using PHP's json_encode() to return some data, retrieved by jQuery's ajax():

Simplified JS:

$.ajax({
    dataType: 'json',
    contentType: 'application/json',
    cache: false,
    type: 'POST',
    url: './api/_imgdown.php',
    error: function(jqXHR, textStatus, errorThrow) {
        console.log(jqXHR, textStatus, errorThrow);
    },
    success: function(data, textStatus, jqXHR) {
        console.log(data, textStatus, jqXHR);
    }
});

The PHP is:

header('Content-Type: application/json; charset=UTF-8');
//default apiResponse
$apiResponse = [
    "status" => 1,
    "message" => "success",
    "data" => null
];

Then when php runs my code, it ends by adding this data:

$apiResponse['data'][] = [
    "mid" => (int)$mid,
    "card_type" => $card_type,
    "header_size" => (int)$headers['Content-Length'],
    "saved_size" => (int)filesize($imgSavePath),
    "saved_path" => $imgSavePath
];
//spit out the JSON
echo json_encode($apiResponse);
exit();

The JSON:

{"status":1,"message":"success","data":[{"mid":340052,"card_type":"kakusei","header_size":48337,"saved_size":48337,"saved_path":"..\/card\/kakusei\/340052.png"}]}

At first it seems valid. My Ajax that retrieves this PHP always ends with parseerror (thus going into the error part of ajax()).

If you copy and paste this JSON on http://jsonlint.com/, it says "Unexpected token " and http://jsonformatter.curiousconcept.com/ says is not valid.

I've tried echo json_encode($apiResponse, JSON_UNESCAPED_SLASHES); even though escaping slashes is ok \/ but made no difference.

But what isn't exactly valid? Wasn't PHP supposed to return valid JSON?

Extra info: Testing on Windows7, Chrome v28.XX, using PHP 5.4.XX on Apache

Questions I've read before actually posting this one:


Update:

Copying from SO into JSONlint gives valid json. So I investigated a little further and noticed the PHP is creating a weird hidden character that is actually making json invalid. See below screenshot. How I fix that? json invalid character

Community
  • 1
  • 1
RaphaelDDL
  • 4,452
  • 2
  • 32
  • 56
  • JSONLint shows it to be good. – Rob W Jul 02 '13 at 14:11
  • your json is valid, and your php is valid. My guess it's your ajax call. Try using `$.getJSON` a simpler ajax call for requesting json – ddavison Jul 02 '13 at 14:11
  • Its showing valid on jsonlint. – Yogesh Suthar Jul 02 '13 at 14:12
  • Valid on jsonformatter too. – Jim Jul 02 '13 at 14:13
  • 1
    Question: Can you try changing `$apiResponse['data'][] = [` to `$apiResponse['data'] = [` and see if it works better ? I don't understand why you are adding your `data` element as an array with another array inside, it should be fine being a single level array (unless you really need it). – Alexandre Danault Jul 02 '13 at 14:14
  • Maybe you have some hidden characters in the string that jQuery chokes on. – silkfire Jul 02 '13 at 14:14
  • 1
    do you have some text output before your php output – DevZer0 Jul 02 '13 at 14:15
  • 1
    To everyone who added comment: Please read the **update**, I've found what is the real problem (that when pasting onto Stackoverflow actually 'fixed', therefore isn't invalid anymore). – RaphaelDDL Jul 02 '13 at 14:16
  • @DevZer0 Nope, I've checked. line 1 starts with ``, no extra spaces or anything. – RaphaelDDL Jul 02 '13 at 14:17
  • 1
    It may be a BOM character but I have no idea why it is there... Could you determine the ASCII code of the first character in the return data? Use `console.log(data.charCodeAt(0))`. – silkfire Jul 02 '13 at 14:19
  • @silkfire `65279`. And now that you said, the encoding I'm saving with my text editor is `utf-8 with bom` (because BOM accepts `áãà` and other stuff without I having to actually convert to the html entities). But testing saving the file as normal utf-8 worked (json is now really valid!). You have any idea what this first character is? – RaphaelDDL Jul 02 '13 at 14:26
  • 2
    It could be that very BOM character indeed. But all my PHP files are always UTF-8 with BOM mark and I echo json all the time exactly like you do and I never get a problem. Encoding issues are always annoying :) I added it as a real answer :) – silkfire Jul 02 '13 at 14:30
  • @Alex-Info.net Just to explain the `$apiResponse['data'][] = [`, 'data' will hold more items so this way the final json will be `"data":[ { /*one object*/ }, { /* another object*/}]`. I simplified my code but I have a loop that actually adds more stuff into the json but wasn't relevant to the problem so I removed for the sake of simplicity.. – RaphaelDDL Jul 02 '13 at 14:31
  • I am pretty sure the json-string is not encoded in the character set the character set your html document is expecting. – Sumurai8 Jul 02 '13 at 14:40

2 Answers2

8

It could be an issue with a BOM mark. Try to save the file as normal UTF-8 instead.

silkfire
  • 24,585
  • 15
  • 82
  • 105
  • 1
    Yeah, as you helped find out, was the BOM char `65279`. I've found another question with this issue http://stackoverflow.com/questions/6538203/how-to-avoid-echoing-character-65279-in-php-this-question-also-relates-to-java The problem is that I need the BOM since the `card_type` might have latin characters such as `áéã` which are not encoded into HTML entities thus bugging when saved without `BOM`. I'll save as normal UTF-8 and try use `htmlentities()` for that and hope to work. Thanks for your time answering! – RaphaelDDL Jul 02 '13 at 14:36
  • 3
    Oh my God. Have searched for an answer for this issue for two days now... Thanks! :-) – curly_brackets Feb 21 '14 at 06:57
-1

I have encountered same problem, but I could not find which file on my Windows is saved in UTF8 with BOM (Even though I have tried to search the files as many as I could).

However, I've found out the workaround. Assuming on the server side I have

die(json_encode(array(
    'OK' => 1
)))
  1. On the $.ajax call, I remove the entry "datatype : 'json'" and I access to the response with the following lines:
success: function (response) {
      var data = $.parseJSON(response); 
      console.log(data.OK); // = 1
  }
  1. On the $.ajax call, I still keep the entry "datatype : 'json'", then I have to access the value inside the response like this

var dataOK = response['OK']; // = 1

Telvin Nguyen
  • 3,569
  • 4
  • 25
  • 39