json_encode повертає NULL?


119

Чомусь пункт "Опис" повертається NULLіз наступним кодом:

<?php
include('db.php');

$result = mysql_query('SELECT * FROM `staff` ORDER BY `id` DESC LIMIT 2') or die(mysql_error());
$rows = array();
while($row = mysql_fetch_assoc($result)){
    $rows[] = $row;
}

echo json_encode($rows);
?>

Ось схема для моєї бази даних:

CREATE TABLE `staff` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` longtext COLLATE utf8_unicode_ci,
  `description` longtext COLLATE utf8_unicode_ci,
  `icon` longtext COLLATE utf8_unicode_ci,
  `date` longtext COLLATE utf8_unicode_ci,
  `company` longtext COLLATE utf8_unicode_ci,
  `companyurl` longtext COLLATE utf8_unicode_ci,
  `appurl` longtext COLLATE utf8_unicode_ci,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

Ось що відображається на сторінці:

[{"id":"4","name":"Noter 2","description":null,"icon":"http:\/\/images.apple.com\/webapps\/productivity\/images\/noter2_20091223182720-thumb.jpg","date":"1262032317","company":"dBelement, LLC","companyurl":"http:\/\/dbelement.com\/","appurl":"http:\/\/noter2.dbelement.com"},{"id":"3","name":"Noter 2","description":null,"icon":"http:\/\/images.apple.com\/webapps\/productivity\/images\/noter2_20091223182720-thumb.jpg","date":"1262032317","company":"dBelement, LLC","companyurl":"http:\/\/dbelement.com\/","appurl":"http:\/\/noter2.dbelement.com"}]

Будь-які ідеї?


Покладемо передусім ключі масиву в лапки.
Joost

Не могли б ви надати інформацію про схему таблиці «персоналу». Чи є стовпець під назвою опис?
мопоке

всі ці поля будуть відлунюватись, якщо я просто зроблю відлуння за $r['description']межами оператора for ()?
tarnfeld

А може, допоможе якийсь приклад контенту з $ r ['description']. Що це за тип даних?
мопоке

Ви могли б зробити скріншот shema бази даних? ;-)
streetparade

Відповіді:


256

Надіюсь, ви отримуєте дані в кодуванні, яке не є utf8: спробуйте поставити mysql_query('SET CHARACTER SET utf8')перед SELECTзапитом.


5
привіт, ця відповідь врятувала мені життя, дякую. У мене була така ж проблема і тут. У мене були значення з не-utf8 символами, як "Validação de Formulários". Я знаю, що це питання вже трохи старе, але це приголомшливість Інтернету !!
fabio

7
mysql_set_charset кращий з міркувань безпеки, оскільки PHP 5.2.3. Докладніше див. У php.net/manual/en/function.mysql-set-charset.php .
masakielastic

3
Тому що UTF8 - це lingua franca в Інтернеті. Замість того, щоб захаращувати API додатковими параметрами та накладними витратами, PHP (жорстко) використовує найпоширеніше кодування, залишаючи вам тягар перетворення, якщо ви використовуєте нечасте (або майже мертве, як у вашому випадку) кодування.
ntd

1
Рекомендований спосіб зробити це змінився. Я спробував відредагувати цю відповідь, щоб включити посилання, але був відхилений. Правильний шлях - у моїй відповіді нижче.
bejs

1
@VeeK недостатньо, щоб ваші поля зберігалися в UTF-8: ви повинні налаштувати свій сервер, щоб відповідати клієнтам у UTF-8. AFAIK акції mysql і mariadb використовують латинську1.
nt

118

Якщо у вас є принаймні PHP 5.5, ви можете використовувати json_last_error_msg () , який поверне рядок із описом проблеми.

Якщо у вас немає 5,5, але ви перебуваєте на / вище 5,3, ви можете скористатися json_last_error (), щоб побачити, у чому проблема.

Він поверне ціле число, яке ви можете використовувати для виявлення проблеми в документації функції . Наразі (2012.01.19) ідентифікаторами є:

0 = JSON_ERROR_NONE
1 = JSON_ERROR_DEPTH
2 = JSON_ERROR_STATE_MISMATCH
3 = JSON_ERROR_CTRL_CHAR
4 = JSON_ERROR_SYNTAX
5 = JSON_ERROR_UTF8

Вони можуть змінитися в наступних версіях, тому краще ознайомитися з посібником.

Якщо ви нижче 5,3, вам не пощастило, немає можливості запитати, у чому помилка.


18

Провідник ntd не вирішив мою проблему. Для тих, хто перебуває в тій же ситуації, ось як я нарешті вирішив цю помилку: просто utf8_enкодування кожного з ваших результатів.

while($row = mysql_fetch_assoc($result)){
    $rows[] = array_map('utf8_encode', $row);
}

Сподіваюся, це допомагає!


У мене також були проблеми з кодуванням. w / змішане кодування. Я знайшов рішення: stackoverflow.com/a/3521396/776345
Paschalis

9

кілька днів тому в мене одна проблема з 1 таблицею.

По-перше, спробуйте:

echo json_encode($rows);
echo json_last_error();  // returns 5 ?

Якщо останній рядок повертає 5, проблема з вашими даними . Я знаю, ваші таблиці знаходяться в UTF-8, але дані не введені . Наприклад, вхід був у файлі txt, але створений на машині Win з дурним кодуванням (в моєму випадку Win-1250 = CP1250) і ці дані були введені в БД.

Рішення? Шукайте нові дані (excel, веб-сторінка), редагуйте вихідний txt-файл через PSPad (або що-небудь ще), змініть кодування на UTF-8 , видаліть усі рядки та тепер покладіть дані з оригіналу. Зберегти. Введіть у БД .

Ви також можете змінити кодування лише на utf-8, а потім змінити всі рядки вручну (надайте значки з спеціальними символами - desc, ...). Добре для рабів ...


або скористайтеся JSON_PARTIAL_OUTPUT_ON_ERRORопцією, щоб побачити проблему (наприклад, поле з UTF8 буде нульовим).
Пітер Краусс

6

Ви повинні передати utf8 закодований рядок у json_encode. Ви можете використовувати utf8_encodeта array_map()функціонувати як нижче:

<?php
    $encoded_rows = array_map('utf8_encode', $rows);
    echo json_encode($encoded_rows);
?>

4

AHHH !!! Це виглядає так неправильно, що болить мені голова. Спробуйте щось більше подібного ...

<?php
include('db.php');

$result = mysql_query('SELECT `id`, `name`, `description`, `icon` FROM `staff` ORDER BY `id` DESC LIMIT 20') or die(mysql_error());
$rows = array();
while($row = mysql_fetch_assoc($result)){
    $rows[] = $row;
}

echo json_encode($rows);
?>
  • Під час повторення mysql_num_rowsслід використовувати <не <=. Ви також повинні кешувати це значення (зберегти його до змінної), а не перераховувати кожен цикл. Хто знає, що це робить під капотом ... (можливо, це буде ефективно, я не дуже впевнений)
  • Вам не потрібно копіювати кожне значення явно так ... ви просто ускладнюєте це. Якщо запит повертає більше значень, ніж ви вказали там, перелічіть лише ті, які ви хочете у своєму SQL.
  • mysql_fetch_arrayповертає значення як на, так keyі на int. Ви не використовуєте індекси, тому не отримуйте їх.

Якщо це справді проблема json_encode, то, можливо, я б запропонував замінити тіло петлі чимось подібним

$rows[] = array_map('htmlentities',$row);

Перхпас там є якісь особливі особливості, які глузують речі ...


[{"id": "4", "name": "Noter 2", "description": null, "icon": "http: \ / \ / images.apple.com \ / webapps \ / продуктивність \ / images \ /noter2_20091223182720-thumb.jpg "," дата ":" 1262032317 "," компанія ":" dBelement, LLC "," companyurl ":" http: \ / \ / dbelement.com \ / "," appurl ":" http: \ / \ / noter2.dbelement.com "}, {" id ":" 3 "," name ":" Noter 2 "," description ": null," icon ":" http: \ / \ / images .apple.com \ / webapps \ / продуктивність \ / images \ /noter2_20091223182720-thumb.jpg "," дата ":" 1262032317 "," компанія ":" dBelement, LLC "," companyurl ":" http: \ / \ /dbelement.com\/","appurl":"http:\/\/noter2.dbelement.com "
tarnfeld

@tarnfield: Ну, це ти хочеш чи ні? О ... у вас є додаткова інформація там ... тут ... дозвольте це виправити.
mpen

так, "опис" повертаєтьсяnull
tarnfeld

Якщо опис повертається, nullто, мабуть, так і є null . Спробуйте echo $row['description'].'<br/>';в цьому циклі і подивіться, що він говорить.
mpen

1
привіт, ця відповідь врятувала мені життя, дякую. У мене була така ж проблема і тут. У мене були значення з не-utf8 символами, як "Validação de Formulários". Я знаю, що це питання вже трохи старе, але це приголомшливість Інтернету !!
fabio


3

Для всіх, хто використовує PDO, рішення подібне до відповіді ntd .

З сторінки PHP PDO :: __ як коментар від користувача Kiipa на live dot com :

Для отримання діаграми UTF-8 ви можете вказати це в DSN.

$ link = новий PDO ("mysql: host = localhost; dbname = DB; charset = UTF8 ");


0

Для мене проблемою, коли json_encode повертає нульове кодування сутності, було тому, що моя jsonSerialize реалізація отримала цілі об'єкти для пов’язаних об'єктів; Я вирішив цю проблему, переконавшись, що я дістав ідентифікатор пов'язаного / асоційованого об'єкта і викликав -> toArray (), коли було більше одного об'єкта, асоційованого з об'єктом, який повинен бути серіалізований json. Зауважте, я говорю про випадки, коли один implements JsonSerializableпро сутність.


-4

У мене була така ж проблема, і рішенням було використовувати мою власну функцію замість json_encode()

echo '["' . implode('","', $row) . '"]';
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.