Почему этот вызов PHP для json_encode бесшумно терпит неудачу - неспособность обрабатывать одиночные кавычки?
У меня есть объект stdClass
с именем $post
, который при сбрасывании через print_r()
возвращает следующее:
stdClass Object (
[ID] => 12981
[post_title] => Alumnus' Dinner Coming Soon
[post_parent] => 0
[post_date] => 2012-01-31 12:00:51
)
Повторение результата вызова json_encode()
на этом объекте приводит к следующему:
{
"ID": "12981",
"post_title": null,
"post_parent": "0",
"post_date": "2012-01-31 12:00:51"
}
Я предполагаю, что что-то с одной цитатой вызывает json_encode
, чтобы задохнуться, но я не знаю, какой формат нужен, чтобы избежать этого. Любые идеи?
EDIT: Исправлено несоответствие в примерах кода. Я запускаю PHP версии 5.3.8
EDIT2: сразу после кодирования объекта я сделал следующее:
echo json_last_error() == JSON_ERROR_UTF8;
Отпечатано 1
, что означает, что произошла следующая ошибка: "Недопустимые символы UTF-8, возможно, неправильно закодированные". json_last_error()
EDIT3: Вызов utf8_decode()
в заголовке сообщения привел к следующему: "Ученик" Ужин "Скоро". Эти данные извлекаются из базы данных MySQL - в частности, заголовок сообщения представляет собой текстовое поле, кодированное UTF-8. Может быть, эта одиночная кавычка неправильно закодирована? Дело в том, что у меня есть приложение с графическим интерфейсом SQL, и оно выглядит правильно.
Ответы
Ответ 1
Перед выполнением запросов вам необходимо установить кодировку соединения. Как это сделать, зависит от API, который вы используете для подключения:
- вызов
mysql_set_charset("utf8")
, если вы используете старый, устаревший API.
- вызов
mysqli_set_charset("utf8")
, если вы используете mysqli
- добавьте параметр
charset
в строку подключения, если вы используете PDO и PHP >= 5.3.6. В более ранних версиях вам нужно выполнить SET NAMES utf8
.
Когда вы получаете данные из MySQL, любой текст будет закодирован в "клиентской кодировке", что, скорее всего, windows-1252, если вы не настроите его иначе. Характер, вызывающий вашу проблему, - это "кулисная цитата", которая рассматривается как 92
в шестнадцатеричном дампе, что подтверждает, что клиент mysql кодирует текст в windows-1252.
Еще одна вещь, которую вы можете рассмотреть, - передать весь текст через utf8_encode
, но в этом случае он не даст правильного результата. PHP utf8_encode
преобразует iso-8859-1 -кодированный текст. В этой кодировке \x92 является непечатаемым управляющим символом, который будет преобразован в непечатаемый управляющий символ в utf-8. Вы можете использовать str_replace("\x92", "'", $input)
, чтобы исправить проблему для этого конкретного символа, но если есть вероятность, что в базе данных будут какие-либо другие символы, отличные от ascii, вы хотите, чтобы клиент использовал UTF-8.
Ответ 2
То, что мне нужно было сделать в прошлом для json_encode по тексту с символами utf8,
json_encode( utf8_encode( $s ) );
и в некоторых случаях
json_encode( htmlspecialchars( utf8_encode( $s ) ) );
the utf8_encode() для обработки специальных символов (обратите внимание, что Encode, а не Decode)
htmlspecialchars() в зависимости от того, как вы хотите использовать строку JSON, вы можете оставить это вне
и, наконец, json_encode(), чтобы получить ваш пакет JSON.
Поскольку вы хотите json_encode для объекта, вам нужно сначала вызвать utf8_encode() для каждой текстовой части или написать простой рекурсивный utf8_encode(). Для примера вашего примера:
function myEncode($o) {
$o->title = utf8_encode($o->title);
return json_encode($o);
}
Ответ 3
У меня была такая же проблема, в то время как JSON, кодирующая php-массив из результатов запроса ODBC, мой сервер OBC настроен с 'en_US.819', является производственным сервером, поэтому я даже не могу его коснуться!!
когда я попытался:
echo json_encode($GLOBALS['response'], true);
Где "respose" представляет собой массив с результатами, он работает так, как предполагалось, так как не существует причудливого char, если это так, json_encode не возвращает пустой.
Решение?.... UTF кодирует результаты при извлечении строк из запроса:
$result = odbc_exec($conn, $sql_query);
$response = array();
while( $row = odbc_fetch_array($result) ) {
$json['pers_identificador'] = $row['pers_identificador'];
$json['nombre_persona'] = utf8_encode( $row['nombre_persona'] );
$json['nombre_1'] = utf8_encode($row['nombre_1'] );
$json['nombre_2'] = utf8_encode($row['nombre_2'] );
array_push($response, $json);
}
Теперь json_encode работает!!!, результирующая строка выглядит примерно так:
{"page_id":300,"max_rows":"100","cant_rows":"12897","datos":
[{"pers_identificador":"301","cedula":"15250068","interno_1":"178202","interno_2":"","nombre_persona":"JOSE JUAN PANDOLFO ZAGORODKO","nombre_1":"JOSE","nombre_2":"JUAN",....
Это исправило мою проблему.
Ответ 4
Я хотел бы сообщить вам об этой проблеме, по ссылке, которую я предлагаю вам использовать упаковщик json_encode, например:
function safe_json_encode($value){
if (version_compare(PHP_VERSION, '5.4.0') >= 0) {
$encoded = json_encode($value, JSON_PRETTY_PRINT);
} else {
$encoded = json_encode($value);
}
switch (json_last_error()) {
case JSON_ERROR_NONE:
return $encoded;
case JSON_ERROR_DEPTH:
return 'Maximum stack depth exceeded'; // or trigger_error() or throw new Exception()
case JSON_ERROR_STATE_MISMATCH:
return 'Underflow or the modes mismatch'; // or trigger_error() or throw new Exception()
case JSON_ERROR_CTRL_CHAR:
return 'Unexpected control character found';
case JSON_ERROR_SYNTAX:
return 'Syntax error, malformed JSON'; // or trigger_error() or throw new Exception()
case JSON_ERROR_UTF8:
$clean = utf8ize($value);
return safe_json_encode($clean);
default:
return 'Unknown error'; // or trigger_error() or throw new Exception()
}
}
function utf8ize($mixed) {
if (is_array($mixed)) {
foreach ($mixed as $key => $value) {
$mixed[$key] = utf8ize($value);
}
} else if (is_string ($mixed)) {
return utf8_encode($mixed);
}
return $mixed;
}
И после определения этих функций вы можете использовать его напрямую,
echo safe_json_encode($response);
Ответ 5
Вы можете попробовать установить кодировку в конфигурации базы данных:
'charset' => 'utf8',
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
)