Грабельки: Google Chrome и JSON через jQuery AJAX
Кто бы мог ожидать, что около часа экспериментов (включая написание минималистичного прототипа) займут заботливо разложенные разработчиками jquery грабельки
Поиск по инету результатов не дал. Поэтому спешу поделиться.
Сразу скажу, проблема оказалась в знаках табуляции в JSON.
А теперь подробнее…
Итак, имеем минимальный прототип, работающий во всех браузерах, кроме гуглохрома.
index.php:
<? header("Content-type: text/html; charset=utf-8");?> <!DOCTYPE html> <html> <head> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script> <script type="text/javascript"> $(function() { $('#do_btn').click(function() { $.ajaxSetup({cache: false}); $.ajax({ method: 'post', url: 'json.php', data: 'ajax=1', dataType: 'json', beforeSend: (function() { $('#status').html('Processing...'); }), complete: (function() { $('#status').html('Complete'); }), success: (function(data) { $('#result').html(data.newhtml); }), error: (function(xmlhttp, textStatus, errorThrown) { $('#error').append('AJAX error: [' + xmlhttp.status + '] ' + xmlhttp.statusText + '; textStatus=' + textStatus + '; errorThrown=' + errorThrown + '<hr/>'); }) }); return false; }); }); </script> </head><body> <a href="#" id="do_btn">[ DO ]</a> <br/><br/> Status: <div id="status">NONE</div> <br/><br/> Result: <div id="result">NONE</div> <br/><br/> ERROR: <div id="error">NONE</div> </body></html>
И json.php
{"newhtml":" html data\n"}
Перед html дата – символ табуляции (\x09)
Во всех современных браузерах получаем то что и ожидалось: в <div id=»#result»> текст «html data». Но в хроме…
ERROR:
AJAX error: [200] OK; textStatus=parsererror; errorThrown=SyntaxError: Unexpected token ILLEGAL
При этом если слегка видоизменить пример, поменяв тип возвращаемого контента на text и скормив его eval’у, все работает. То есть json корректен.
Это же подтверждается json.org:
char
any-Unicode-character-
except-»-or-\-or-
control-character
\»
\\
\/
\b
\f
\n
\r
\t
\u four-hex-digits
То есть в JSON строковых данных не допускается лишь символы \ и «. Табуляция допускается.
После того как проблема была продиагностирована, пришло и решение: замена символа табуляции (\x09) на \t (не путать с литералом javascript/php/C++! Нужно чтобы было именно 2 символа \ и t).
4 Комментариев4 Комментариев
Оставить комментарий
А по-моему всё верно. Читаем стандарт:
http://www.ietf.org/rfc/rfc4627.txt
В частности Page 4.
string = quotation-mark *char quotation-mark
char = unescaped /
escape (
%x22 / ; » quotation mark U+0022
%x5C / ; \ reverse solidus U+005C
%x2F / ; / solidus U+002F
%x62 / ; b backspace U+0008
%x66 / ; f form feed U+000C
%x6E / ; n line feed U+000A
%x72 / ; r carriage return U+000D
%x74 / ; t tab U+0009
%x75 4HEXDIG ) ; uXXXX U+XXXX
escape = %x5C ; \
quotation-mark = %x22 ; »
unescaped = %x20-21 / %x23-5B / %x5D-10FFFF
Важное в «unescaped = %x20-21 / %x23-5B / %x5D-10FFFF»
Вдогонку, похоже serializer тебе неверное отдал. Или это собиралось ручками ?
Джейсон-сериализатор мой собственный. А в приведенном минималистичном тестовом примере – вообще готовая строка
По поводу RFC – таки действительно, судя по всему, я неправ
Но тем не менее, факт, что если сделать тип text и потом
eval("var jsondata=" + data);
все корректно парсится с символами табуляции в строке и в jsondata.newhtml получаем нужное
… во всех браузерах, включая хром.