json_encode mengembalikan NULL?

119

Untuk beberapa alasan item "deskripsi" kembali NULLdengan kode berikut:

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

Berikut skema untuk database saya:

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

Inilah yang digaungkan di halaman:

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

Ada ide?

tarnfeld
sumber
Mari kita letakkan kunci array dalam tanda kutip, pertama-tama.
Joost
Bisakah Anda memberikan informasi tentang skema tabel "staf" Anda. Apakah ada kolom yang disebut deskripsi?
mopoke
semua bidang ini akan bergema jika saya hanya melakukan gema di $r['description']luar pernyataan for ()?
tarnfeld
Atau mungkin beberapa contoh konten dari $ r ['description'] akan membantu. Jenis data apa itu?
mopoke
bisakah Anda membuat screenshot dari database shema? ;-)
parade jalanan

Jawaban:

256

Saya yakin Anda mengambil data dalam pengkodean non-utf8: coba letakkan mysql_query('SET CHARACTER SET utf8')sebelum SELECTkueri Anda .

ntd
sumber
5
hai, jawaban ini menyelamatkan hidup saya, terima kasih. Saya mengalami masalah yang sama di sini. Saya memiliki nilai dengan karakter non-utf8 seperti "Validação de Formulários". Saya tahu pertanyaan ini agak kuno sekarang, tapi itulah kehebatan internet !!
fabio
7
mysql_set_charset lebih baik untuk alasan keamanan sejak PHP 5.2.3. Lihat php.net/manual/en/function.mysql-set-charset.php untuk detailnya.
masakielastic
3
Karena UTF8 adalah lingua franca di web. Alih-alih mengacaukan API dengan parameter dan overhead tambahan, PHP (secara ketat) menggunakan pengkodean yang paling umum, menyerahkan kepada Anda beban konversi jika Anda menggunakan pengkodean yang tidak umum (atau hampir mati, seperti dalam kasus Anda).
ntd
1
Cara yang disarankan untuk melakukan ini sekarang telah berubah. Saya mencoba mengedit jawaban ini untuk menyertakan tautan tetapi ditolak. Cara yang benar ada pada jawaban saya di bawah ini.
bejs
1
@VeeK saja tidak cukup hanya dengan bidang Anda yang disimpan di UTF-8: Anda harus mengkonfigurasi server Anda untuk menjawab klien di UTF-8. AFAIK stock mysql dan mariadb menggunakan latin1.
ntd
118

Jika Anda memiliki setidaknya PHP 5.5, Anda dapat menggunakan json_last_error_msg () , yang akan mengembalikan string yang menjelaskan masalah.

Jika Anda tidak memiliki 5.5, tetapi berada di / di atas 5.3, Anda dapat menggunakan json_last_error () untuk melihat apa masalahnya.

Ini akan mengembalikan integer, yang dapat Anda gunakan untuk mengidentifikasi masalah dalam dokumentasi fungsi . Saat ini (2012.01.19), pengenalnya adalah:

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

Ini dapat berubah di versi mendatang, jadi lebih baik untuk membaca manual.

Jika Anda berada di bawah 5.3, Anda kurang beruntung, tidak ada cara untuk menanyakan apa kesalahannya.

K. Norbert
sumber
18

Jawaban ntd tidak menyelesaikan masalah saya. Bagi mereka yang berada dalam situasi yang sama, berikut adalah bagaimana saya akhirnya menangani kesalahan ini: Cukup utf8_encode setiap hasil Anda.

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

Semoga membantu!

Pablo Abdelhay
sumber
Saya juga mengalami masalah encoding. w / pengkodean campuran. solusi yang saya temukan: stackoverflow.com/a/3521396/776345
Paschalis
9

beberapa hari yang lalu saya mengalami masalah yang SAMA dengan 1 tabel.

Pertama coba:

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

Jika baris terakhir mengembalikan 5, masalahnya ada pada data Anda . Saya tahu, tabel Anda dalam UTF-8, tetapi tidak memasukkan data . Misalnya input dalam file txt, tetapi dibuat pada mesin Win dengan pengkodean bodoh (dalam kasus saya Win-1250 = CP1250) dan data ini telah dimasukkan ke dalam DB.

Larutan? Cari data baru (excel, halaman web), edit file txt sumber melalui PSPad (atau apa pun), ubah encoding ke UTF-8 , hapus semua baris dan sekarang letakkan data dari aslinya. Menyimpan. Masuk ke DB .

Anda juga hanya dapat mengubah encoding ke utf-8 dan kemudian mengubah semua baris secara manual (berikan kolom dengan karakter khusus - desc, ...). Baik untuk budak ...

Ivo Urbanek
sumber
atau gunakan JSON_PARTIAL_OUTPUT_ON_ERRORopsi untuk melihat masalah (mis. bidang dengan UTF8 akan menjadi nol).
Peter Krauss
6

Anda harus meneruskan string yang dienkode utf8 di json_encode. Anda dapat menggunakan utf8_encodedan array_map()berfungsi seperti di bawah ini:

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

AHHH !!! Ini terlihat sangat salah sehingga sakit kepala saya. Coba sesuatu yang lebih seperti ini ...

<?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);
?>
  • Saat iterasi mysql_num_rowsAnda harus menggunakan <tidak<= . Anda juga harus menyimpan nilai ini ke cache (menyimpannya ke variabel) daripada menghitung ulang setiap loop. Siapa yang tahu apa yang dilakukannya di bawah tenda ... (mungkin efisien, saya tidak begitu yakin)
  • Anda tidak perlu menyalin setiap nilai secara eksplisit seperti itu ... Anda hanya mempersulit diri Anda sendiri. Jika kueri mengembalikan lebih banyak nilai daripada yang Anda cantumkan di sana, daftarkan hanya yang Anda inginkan di SQL Anda.
  • mysql_fetch_arraymengembalikan nilai by keydan by int. Anda tidak menggunakan indeks, jadi jangan ambil.

Jika ini benar-benar masalah json_encode, mungkin saya sarankan untuk mengganti badan loop dengan sesuatu seperti

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

Perhpas ada beberapa karakter khusus di sana yang mengacaukan ...

mpen
sumber
[{"id": "4", "name": "Noter 2", "description": null, "icon": "http: \ / \ / images.apple.com \ / webapps \ / produktivitas \ / gambar \ /noter2_20091223182720-thumb.jpg "," date ":" 1262032317 "," perusahaan ":" dBelement, LLC "," companyurl ":" http: \ / \ / dbelement.com \ / "," appurl ":" http: \ / \ / noter2.dbelement.com "}, {" id ":" 3 "," name ":" Noter 2 "," description ": null," icon ":" http: \ / \ / images .apple.com \ / webapps \ / produktivitas \ / images \ /noter2_20091223182720-thumb.jpg "," date ":" 1262032317 "," perusahaan ":" dBelement, LLC "," companyurl ":" http: \ / \ /dbelement.com\/","appurl":"http:\/\/noter2.dbelement.com "
tarnfeld
@tarnfield: Nah, apakah itu yang Anda inginkan atau tidak? Oh..Anda punya beberapa info tambahan di sana ... di sini ... biarkan saya memperbaikinya untuk Anda.
mpen
ya "deskripsi" kembalinull
tarnfeld
Jika deskripsinya kembali nullmaka mungkin memang begitu null . Coba echo $row['description'].'<br/>';di loop itu dan lihat apa yang dikatakannya.
mpen
1
hai, jawaban ini menyelamatkan hidup saya, terima kasih. Saya mengalami masalah yang sama di sini. Saya memiliki nilai dengan karakter non-utf8 seperti "Validação de Formulários". Saya tahu pertanyaan ini agak kuno sekarang, tapi itulah kehebatan internet !!
fabio
3

Untuk siapa pun yang menggunakan PDO, solusinya mirip dengan jawaban NTD .

Dari halaman konstruksi PHP PDO :: __ , sebagai komentar dari pengguna Kiipa di live dot com :

Untuk mendapatkan rangkaian karakter UTF-8 Anda dapat menentukannya di DSN.

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

MichaelS
sumber
0

Bagi saya, masalah di mana json_encode akan mengembalikan pengkodean null entitas adalah karena implementasi jsonSerialize saya mengambil seluruh objek untuk entitas terkait; Saya memecahkan masalah dengan memastikan bahwa saya mengambil ID dari entitas terkait / terkait dan memanggil -> toArray () ketika ada lebih dari satu entitas yang terkait dengan objek yang akan dijadikan serialisasi json. Perhatikan, saya berbicara tentang kasus di mana satu implements JsonSerializableentitas.

Victor S
sumber
-4

Saya memiliki masalah yang sama dan solusinya adalah menggunakan fungsi saya sendiri, bukan json_encode()

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