json_encode gibt NULL zurück?

119

Aus irgendeinem Grund wird der Artikel "Beschreibung" NULLmit dem folgenden Code zurückgegeben:

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

Hier ist das Schema für meine Datenbank:

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

Folgendes wird auf der Seite wiedergegeben:

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

Irgendwelche Ideen?

Tarnfeld
quelle
Lassen Sie uns die Array-Schlüssel zunächst in Anführungszeichen setzen.
Joost
Könnten Sie Informationen zum Schema Ihrer "Staff" -Tabelle bereitstellen? Gibt es eine Spalte namens Beschreibung?
Mopoke
Alle diese Felder werden wiedergegeben, wenn ich nur ein Echo $r['description']außerhalb der for () -Anweisung mache .
Tarnfeld
Oder vielleicht würde ein Beispielinhalt aus $ r ['description'] helfen. Um welchen Datentyp handelt es sich?
Mopoke
Könnten Sie einen Screenshot des Datenbankschemas machen? ;-)
Straßenparade

Antworten:

255

Ich wette, Sie rufen Daten in Nicht-Utf8-Codierung ab: Versuchen Sie, sie mysql_query('SET CHARACTER SET utf8')vor Ihre SELECTAbfrage zu stellen.

ntd
quelle
5
Hallo, diese Antwort hat mir das Leben gerettet, danke. Ich hatte hier das gleiche Problem. Ich hatte Werte mit Nicht-Utf8-Zeichen wie "Validação de Formulários". Ich weiß, dass diese Frage jetzt ein bisschen alt ist, aber das ist die Großartigkeit des Internets !!
Fabio
7
mysql_set_charset ist aus Sicherheitsgründen seit PHP 5.2.3 besser. Weitere Informationen finden Sie unter php.net/manual/en/function.mysql-set-charset.php .
masakielastic
3
Weil UTF8 die Verkehrssprache im Web ist. Anstatt die API mit zusätzlichen Parametern und Overhead zu überladen, verwendet PHP (genau genommen) die am häufigsten verwendete Codierung, sodass Sie die Konvertierungslast tragen, wenn Sie eine ungewöhnliche (oder wie in Ihrem Fall fast tote) Codierung verwenden.
1.
1
Die empfohlene Vorgehensweise hat sich nun geändert. Ich habe versucht, diese Antwort so zu bearbeiten, dass sie einen Link enthält, wurde jedoch abgelehnt. Der richtige Weg ist in meiner Antwort unten.
Bejs
1
@VeeK Es reicht nicht aus, Ihre Felder in UTF-8 zu speichern: Sie müssen Ihren Server so konfigurieren , dass er auf Clients in UTF-8 antwortet . AFAIK stock mysql und mariadb verwenden latin1.
ntd
118

Wenn Sie mindestens PHP 5.5 haben, können Sie json_last_error_msg () verwenden , das eine Zeichenfolge zurückgibt , die das Problem beschreibt.

Wenn Sie nicht über 5.5 verfügen, aber über 5.3 verfügen, können Sie mit json_last_error () das Problem ermitteln.

Es wird eine Ganzzahl zurückgegeben, mit der Sie das Problem in der Dokumentation der Funktion identifizieren können . Derzeit (19.01.2012) lauten die Kennungen:

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

Diese können sich in zukünftigen Versionen ändern. Lesen Sie daher besser das Handbuch.

Wenn Sie unter 5,3 sind, haben Sie kein Glück, es gibt keine Möglichkeit zu fragen, was der Fehler war.

K. Norbert
quelle
18

Die Antwort von ntd hat mein Problem nicht gelöst. Für diejenigen in der gleichen Situation, hier ist, wie ich diesen Fehler endlich behandelt habe: Nur utf8_encode jedes Ihrer Ergebnisse.

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

Ich hoffe es hilft!

Pablo Abdelhay
quelle
Ich hatte auch Codierungsprobleme. mit gemischter Codierung. Lösung, die ich gefunden habe: stackoverflow.com/a/3521396/776345
Paschalis
9

Vor ein paar Tagen habe ich das gleiche Problem mit 1 Tabelle.

Versuchen Sie zunächst:

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

Wenn die letzte Zeile 5 zurückgibt, liegt das Problem bei Ihren Daten . Ich weiß, Ihre Tabellen sind in UTF-8, aber keine eingegebenen Daten . Zum Beispiel war die Eingabe in einer txt-Datei, wurde aber auf einem Win-Computer mit dummer Codierung (in meinem Fall Win-1250 = CP1250) erstellt und diese Daten wurden in die Datenbank eingegeben.

Lösung? Suchen Sie nach neuen Daten (Excel, Webseite), bearbeiten Sie die Quell-TXT-Datei über PSPad (oder was auch immer), ändern Sie die Codierung in UTF-8 , löschen Sie alle Zeilen und fügen Sie jetzt Daten aus dem Original ein. Sparen. In DB eingeben .

Sie können die Codierung auch nur in utf-8 ändern und dann alle Zeilen manuell ändern (geben Sie Spalten mit speziellen Zeichen an - desc, ...). Gut für Sklaven ...

Ivo Urbanek
quelle
oder verwenden Sie die JSON_PARTIAL_OUTPUT_ON_ERROROption , um das Problem anzuzeigen (z. B. ist das Feld mit UTF8 null).
Peter Krauss
6

Sie sollten eine utf8-codierte Zeichenfolge in json_encode übergeben. Sie können wie folgt verwenden utf8_encodeund array_map()funktionieren:

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

ÄHHH!!! Das sieht so falsch aus, dass es meinen Kopf verletzt. Versuchen Sie etwas ähnlicheres ...

<?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);
?>
  • Wenn Sie darüber iterieren mysql_num_rows, sollten Sie <nicht verwenden <=. Sie sollten diesen Wert auch zwischenspeichern (in einer Variablen speichern), anstatt jede Schleife neu zählen zu lassen. Wer weiß, was es unter der Haube tut ... (könnte effizient sein, ich bin mir nicht sicher)
  • Sie müssen nicht jeden Wert explizit so kopieren ... Sie machen es sich nur schwerer. Wenn die Abfrage mehr Werte zurückgibt, als Sie dort aufgelistet haben, listen Sie nur die gewünschten in Ihrem SQL auf.
  • mysql_fetch_arraygibt die Werte nach keyund nach zurück int. Sie verwenden die Indizes nicht, holen Sie sie also nicht ab.

Wenn dies wirklich ein Problem ist json_encode, kann ich vorschlagen, den Körper der Schleife durch so etwas zu ersetzen

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

Vielleicht gibt es da drin einige spezielle Zeichen, die die Dinge durcheinander bringen ...

mpen
quelle
[{"id": "4", "name": "Noter 2", "description": null, "icon": "http: \ / \ / images.apple.com \ / webapps \ / Produktivität \ / 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 \ / Produktivität \ / images \ /noter2_20091223182720-thumb.jpg "," Datum ":" 1262032317 "," Unternehmen ":" dBelement, LLC "," Unternehmen ":" http: \ / \ \ " /dbelement.com\/","appurl":"http:\/\/noter2.dbelement.com "
Tarnfeld
@ Tarnfield: Nun, ist es das was du willst oder nicht? Oh ... du hast da ein paar zusätzliche Informationen ... hier ... lass mich das für dich reparieren.
Mpen
yeah "description" kehrt zurücknull
tarnfeld
Wenn die Beschreibung zurückkehrt, nullist dies wahrscheinlich der Fall null . Versuchen Sie es echo $row['description'].'<br/>';in dieser Schleife und sehen Sie, was darin steht.
Mpen
1
Hallo, diese Antwort hat mir das Leben gerettet, danke. Ich hatte hier das gleiche Problem. Ich hatte Werte mit Nicht-Utf8-Zeichen wie "Validação de Formulários". Ich weiß, dass diese Frage jetzt ein bisschen alt ist, aber das ist die Großartigkeit des Internets !!
Fabio
3

Für alle, die PDO verwenden, ähnelt die Lösung der Antwort von ntd .

Von der PHP PDO :: __ Konstruktionsseite als Kommentar des Benutzers Kiipa bei live dot com :

Um einen UTF-8-Zeichensatz zu erhalten, können Sie diesen im DSN angeben.

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

MichaelS
quelle
0

Für mich bestand ein Problem, bei dem json_encode die Nullcodierung einer Entität zurückgab, darin, dass meine jsonSerialize-Implementierung ganze Objekte für verwandte Entitäten abgerufen hat. Ich habe das Problem gelöst, indem ich sichergestellt habe, dass ich die ID der zugehörigen / zugeordneten Entität abgerufen und -> toArray () aufgerufen habe, wenn dem zu serialisierenden Objekt mehr als eine Entität zugeordnet war. Beachten Sie, ich spreche von Fällen, in denen es implements JsonSerializableum Entitäten geht.

Victor S.
quelle
-4

Ich hatte das gleiche Problem und die Lösung bestand darin, stattdessen meine eigene Funktion zu verwenden json_encode()

echo '["' . implode('","', $row) . '"]';
Laci
quelle