json_encode zwraca NULL?

119

Z jakiegoś powodu pozycja „opis” wraca NULLz następującym kodem:

<?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);
?>

Oto schemat mojej bazy danych:

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

Oto, co jest echem na stronie:

[{"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"}]

Jakieś pomysły?

tarnfeld
źródło
Najpierw umieśćmy klucze tablic w cudzysłowach.
Joost
Czy mógłbyś podać informacje na temat schematu tabeli personelu? Czy istnieje kolumna o nazwie opis?
mopoke
wszystkie te pola odbijają się echem, jeśli po prostu wykonam echo $r['description']poza instrukcją for ()?
tarnfeld
A może pomocna byłaby przykładowa treść z $ r ['description']. Jaki to typ danych?
mopoke
czy mógłbyś zrobić zrzut ekranu shema bazy danych? ;-)
parada uliczna

Odpowiedzi:

256

Założę się, że pobierasz dane w kodowaniu innym niż utf8: spróbuj umieścić je mysql_query('SET CHARACTER SET utf8')przed SELECTzapytaniem.

ntd
źródło
5
cześć, ta odpowiedź uratowała mi życie, dziękuję. Tu miałem ten sam problem. Miałem wartości ze znakami innymi niż utf8, takie jak „Validação de Formulários”. Wiem, że to pytanie jest teraz trochę stare, ale to jest niesamowity internet !!
fabio
7
mysql_set_charset jest lepszy ze względów bezpieczeństwa od PHP 5.2.3. Aby uzyskać szczegółowe informacje, zobacz php.net/manual/en/function.mysql-set-charset.php .
masakielastic
3
Ponieważ UTF8 to lingua franca w sieci. Zamiast zaśmiecać API dodatkowymi parametrami i narzutem, PHP (ściśle) używa najpopularniejszego kodowania, pozostawiając na Tobie ciężar konwersji, jeśli używasz nietypowego (lub prawie martwego, jak w twoim przypadku) kodowania.
ntd
1
Zalecany sposób robienia tego zmienił się. Próbowałem edytować tę odpowiedź, aby dołączyć link, ale została odrzucona. Moja odpowiedź poniżej zawiera właściwy sposób.
bejs
1
@VeeK nie wystarczy, aby Twoje pola były przechowywane w UTF-8: musisz skonfigurować serwer, aby odpowiadał klientom w UTF-8. AFAIK Stock mysql i mariadb używają latin1.
ntd
118

Jeśli masz co najmniej PHP 5.5, możesz użyć json_last_error_msg () , która zwróci napis opisujący problem.

Jeśli nie masz wersji 5.5, ale jesteś na / powyżej 5.3, możesz użyć json_last_error (), aby zobaczyć, w czym tkwi problem.

Zwróci liczbę całkowitą, której możesz użyć do zidentyfikowania problemu w dokumentacji funkcji . Obecnie (2012.01.19) identyfikatory to:

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

Mogą się one zmienić w przyszłych wersjach, więc lepiej zapoznać się z instrukcją.

Jeśli jesteś poniżej 5,3, nie masz szczęścia, nie ma możliwości spytania o błąd.

K. Norbert
źródło
18

ntd's anwser nie rozwiązał mojego problemu. Dla tych w tej samej sytuacji, oto jak w końcu poradziłem sobie z tym błędem: Po prostu utf8_encode każdy z wyników.

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

Mam nadzieję, że to pomoże!

Pablo Abdelhay
źródło
Miałem też problemy z kodowaniem. z kodowaniem mieszanym. rozwiązanie, które znalazłem: stackoverflow.com/a/3521396/776345
Paschalis
9

kilka dni temu mam TEN SAM problem z 1 stolikiem.

Najpierw spróbuj:

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

Jeśli ostatnia linia zwraca 5, problem dotyczy twoich danych . Wiem, twoje tabele są w UTF-8, ale nie wprowadzono danych . Na przykład dane wejściowe były w pliku txt, ale utworzone na maszynie Win z głupim kodowaniem (w moim przypadku Win-1250 = CP1250) i te dane zostały wprowadzone do bazy danych.

Rozwiązanie? Poszukaj nowych danych (Excel, strona internetowa), edytuj źródłowy plik txt przez PSPad (lub cokolwiek innego), zmień kodowanie na UTF-8 , usuń wszystkie wiersze i umieść dane z oryginału. Zapisać. Wejdź do DB .

Możesz także zmienić tylko kodowanie na utf-8, a następnie ręcznie zmienić wszystkie wiersze (podaj cols ze specjalnymi znakami - desc, ...). Dobre dla niewolników ...

Ivo Urbanek
źródło
lub użyj JSON_PARTIAL_OUTPUT_ON_ERRORopcji, aby zobaczyć problem (np. pole z UTF8 będzie puste).
Peter Krauss
6

Powinieneś przekazać zakodowany ciąg utf8 w json_encode. Możesz używać utf8_encodei array_map()funkcjonować jak poniżej:

<?php
    $encoded_rows = array_map('utf8_encode', $rows);
    echo json_encode($encoded_rows);
?>
koder
źródło
4

AHHH !!! To wygląda tak źle, że boli mnie głowa. Spróbuj czegoś bardziej podobnego ...

<?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);
?>
  • Podczas iteracji nad mysql_num_rowsnależy użyć <nie <=. Powinieneś także buforować tę wartość (zapisać ją w zmiennej) zamiast ponownie liczyć każdą pętlę. Kto wie, co robi pod maską ... (może być wydajne, nie jestem pewien)
  • Nie musisz wyraźnie kopiować każdej wartości ... po prostu utrudniasz sobie to. Jeśli zapytanie zwraca więcej wartości niż te, które zostały tam wymienione, wymień tylko te, które chcesz umieścić w swoim SQL.
  • mysql_fetch_arrayzwraca wartości zarówno przez, jak keyi przez int. Nie używasz indeksów, więc ich nie pobieraj.

Jeśli naprawdę jest z tym problem json_encode, to czy mogę zasugerować wymianę korpusu pętli na coś podobnego

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

Może są tam jakieś specjalne znaki, które wszystko psują ...

mpen
źródło
[{"id": "4", "name": "Noter 2", "description": null, "icon": "http: \ / \ / images.apple.com \ / webapps \ / produktywność \ / 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 \ / produktywność \ / images \ /noter2_20091223182720-thumb.jpg "," date ":" 1262032317 "," company ":" dBelement, LLC "," companyurl ":" http: \ / \ /dbelement.com\/","appurl":"http:\/\/noter2.dbelement.com ”
tarnfeld
@tarnfield: Cóż, czy tego chcesz, czy nie? Och ... masz tam dodatkowe informacje ... tutaj ... pozwól, że naprawię to dla ciebie.
otwarte
tak, "opis" zwracanull
tarnfeld
Jeśli opis wraca, nullto prawdopodobnie tak null . Spróbuj echo $row['description'].'<br/>';w tej pętli i zobacz, co mówi.
otwarte
1
cześć, ta odpowiedź uratowała mi życie, dziękuję. Tu miałem ten sam problem. Miałem wartości ze znakami innymi niż utf8, takie jak „Validação de Formulários”. Wiem, że to pytanie jest teraz trochę stare, ale to jest niesamowity internet !!
fabio
3

Dla każdego, kto używa PDO, rozwiązanie jest podobne do odpowiedzi ntd .

Ze strony PHP PDO :: __ construct , jako komentarz od użytkownika Kiipa na live dot com :

Aby uzyskać zestaw znaków UTF-8, możesz to określić w DSN.

$ link = new PDO ("mysql: host = localhost; dbname = DB; charset = UTF8 ");

Michael S.
źródło
0

Dla mnie problem polegający na tym, że json_encode zwróciłby kodowanie null jednostki, był taki, że moja implementacja jsonSerialize pobierała całe obiekty dla powiązanych jednostek; Rozwiązałem problem, upewniając się, że pobrałem identyfikator powiązanej / skojarzonej jednostki i wywołałem -> toArray (), gdy istniało więcej niż jedna jednostka skojarzona z obiektem do serializacji json. Uwaga, mówię o przypadkach, w których jeden dotyczy implements JsonSerializablepodmiotów.

Victor S.
źródło
-4

Miałem ten sam problem i rozwiązaniem było użycie własnej funkcji zamiast json_encode()

echo '["' . implode('","', $row) . '"]';
Laci
źródło