Mengapa json_encode mengembalikan string kosong


107

Saya memiliki struktur php sederhana dengan 3 array bersarang.

Saya tidak menggunakan objek tertentu dan saya membangun sendiri array dengan 2 loop bersarang.

Berikut adalah contoh var_dump dari array yang ingin saya ubah ke Json.

array (size=2)
  'tram B' => 
    array (size=2)
      0 => 
        array (size=3)
          'name' => string 'Ile Verte' (length=9)
          'distance' => int 298
          'stationID' => int 762
      1 => 
        array (size=3)
          'name' => string 'La Tronche Hôpital' (length=18)
          'distance' => int 425
          'stationID' => int 771
  16 => 
    array (size=4)
      0 => 
        array (size=3)
          'name' => string 'Bastille' (length=8)
          'distance' => int 531
          'stationID' => int 397
      1 => 
        array (size=3)
          'name' => string 'Xavier Jouvin' (length=13)
          'distance' => int 589
          'stationID' => int 438

Di skrip lain saya memiliki struktur yang mirip dan json_encodeberfungsi dengan baik. Jadi saya tidak mengerti mengapa json_encodetidak bekerja di sini.

Edit: sepertinya ada masalah dengan encoding. Ketika mb_detect_encodingmengembalikan ASCII, json_encodeberfungsi tetapi ketika mengembalikan UTF8, itu tidak berfungsi lagi.

Edit2: json_last_error()mengembalikan JSON_ERROR_UTF8yang berarti: Karakter UTF-8 cacat, mungkin salah dienkode .


Manual PHP mengatakan This function only works with UTF-8 encoded data.jadi seharusnya tidak ada masalah dengan pengkodean.
MahanGM

13
Coba gunakan utf8_encode()pada namebidang array Anda sebelum Anda menyerahkan string ke json_encode().
MahanGM

Terima kasih ! Saya baru saja menemukan solusi ini yang memecahkan masalah saya.
Matthieu Riegler

Ya, lihat jawabannya. Semoga berhasil.
MahanGM

3
Gunakan JSON_PARTIAL_OUTPUT_ON_ERRORopsi untuk melihat masalah (mis. Bidang dengan UTF8 akan menjadi nol).
Peter Krauss

Jawaban:


255

Nah setelah 2 jam penggalian (cf Editan)

Saya menemukan hal berikut:

  • Dalam kasus saya ini adalah masalah pengkodean
  • mb_detect_encoding mengembalikan mungkin respons yang salah, beberapa string mungkin bukan UTF-8
  • menggunakan utf8_encode()pada string itu memecahkan masalah saya, tetapi lihat catatan di bawah

Berikut adalah fungsi rekursif yang dapat mengubah paksa ke UTF-8 semua string yang terdapat dalam sebuah array:

function utf8ize($d) {
    if (is_array($d)) {
        foreach ($d as $k => $v) {
            $d[$k] = utf8ize($v);
        }
    } else if (is_string ($d)) {
        return utf8_encode($d);
    }
    return $d;
}

Gunakan seperti ini:

echo json_encode(utf8ize($data));

Catatan: utf8_encode () mengkodekan string ISO-8859-1 ke UTF-8 sesuai dengan dokumen jadi jika Anda tidak yakin dengan input encoding iconv () atau mb_convert_encoding () mungkin opsi yang lebih baik seperti yang dicatat dalam komentar dan solusi lainnya.


4
Terima kasih atas solusi Anda ... namun, satu catatan tambahan: Ubah } else {menjadi } else if (is_string ($d)) {; jika tidak, Anda akan mengubah segalanya menjadi string (mis. INTakan menjadi a STRING).
Paul Peelen

3
Anda baru saja menyelamatkan hidup saya. Saya akan mengakhiri semuanya sampai saya menemukan fungsi ini !! Terima kasih.
silversunhunter

2
WTF! Terima kasih telah membagikan solusi Anda. Saya dapat melihat bahwa ini akan membutuhkan banyak penggalian untuk dipecahkan, dan saya berterima kasih kepada Anda karena melakukan itu dan berbagi.
keris

1
Setelah tiga hari debugging, aku bisa menciummu sekarang.
AJB

2
Jika membaca dari database cukup gunakan, $ conn-> set_charset ("utf8");
Andrew Briggs

36

Matthieu Riegler menyajikan solusi yang sangat bagus namun saya harus sedikit memodifikasinya untuk menangani objek juga:

function utf8ize($d) {
    if (is_array($d)) 
        foreach ($d as $k => $v) 
            $d[$k] = utf8ize($v);

     else if(is_object($d))
        foreach ($d as $k => $v) 
            $d->$k = utf8ize($v);

     else 
        return utf8_encode($d);

    return $d;
}

Satu catatan lagi: json_last_error () mungkin berguna dalam debugging fungsi json_encode () / json_encode ().


Bukankah seharusnya elseifbukan else if? (yaitu tidak boleh kosong).
Uwe Keim

2
@UweKeim menurut dokumentasi PHP "elseif dan lain jika hanya akan dianggap persis sama saat menggunakan tanda kurung kurawal" yang berarti mereka setara selama Anda tidak menggunakan notasi titik dua, misalnyaif(): elseif:
Adam Bubela

1
Kerja bagus. PHP adalah sampah dan orang-orang seperti Anda mencegahnya pergi ke tempat sampah.
Lonnie Best

Anda harus memasukkan else if(is_int($d)||is_bool($d)) return $d;sebelum yang terakhir, karena:{"success":true, "message":"Ⲃⲟⲟ𝓵ⲉⲁⲛ ⲁⲛⲇ Ⲓⲛϯⲉ𝓰ⲉꞅ𝛓"}
David Refoua

Seperti yang direkomendasikan @ paul-peelen kepada @ matthieu-riegler: Ubah yang terakhir elseuntuk else if(is_string ($d)); jika tidak, Anda akan mengubah segalanya menjadi string (mis. INTakan menjadi a STRING).
Bruno Serrano

30

Bagi saya, jawaban untuk masalah ini adalah pengaturan charset=utf8koneksi PDO saya.

$dbo = new PDO('mysql:host=localhost;dbname=yourdb;charset=utf8', $username, $password);

2
Atau dalam fungsi mysqli: mysqli_set_charset ($ connection, "utf8");
pengguna18099

Ini adalah petunjuk untuk solusi saya. Penyebab koneksi msqli sedikit berbeda. Panggil saja $mysqli->set_charset("utf8");setelah melakukan penanganan database Anda.
MaggusK

Silakan gunakan utf8mb4di versi MySQL terbaru. utf8sudah usang.
Dharman

10

Adam Bubela juga menyajikan solusi yang sangat bagus yang membantu saya menyelesaikan masalah saya, dan berikut adalah fungsi yang disederhanakan:

function utf8ize($d)
{ 
    if (is_array($d) || is_object($d))
        foreach ($d as &$v) $v = utf8ize($v);
    else
        return utf8_encode($d);

    return $d;
}

1
Saya suka yang ini karena menyimpan kuncinya.
dev0

7

Saya memiliki masalah yang sama persis di PHP 5.6. Saya menggunakan Open Server + Nginx pada Windows 7. Semua charset disetel ke UTF-8. Secara teori, menurut dokumentasi resmi , bendera

JSON_UNESCAPED_UNICODE

harus menyelesaikan ini. Sayangnya ini bukan kasus saya. Saya tidak tahu kenapa. Semua potongan di atas tidak menyelesaikan masalah saya, jadi saya telah menemukan implementasi saya sendiri. Saya percaya itu bisa membantu seseorang. Setidaknya, huruf Rusia lulus ujian.

function utf8ize($d) {
    if (is_array($d) || is_object($d)) {
        foreach ($d as &$v) $v = utf8ize($v);
    } else {
        $enc   = mb_detect_encoding($d);

        $value = iconv($enc, 'UTF-8', $d);
        return $value;
    }

    return $d;
}

4

Jawaban yang diterima ini berhasil. Tetapi jika Anda mendapatkan data Anda dari MySQL (seperti yang saya lakukan sebelumnya) ada cara yang lebih mudah.

Setelah Anda membuka database Anda, sebelum Anda membuat kueri, Anda dapat mengatur set karakter menggunakan mysqli sebagai berikut:

/* change character set to utf8 | Procedural*/
if (!mysqli_set_charset($link, "utf8")) {
    printf("Error loading character set utf8: %s\n", mysqli_error($link));
    exit();
}

ATAU

/* change character set to utf8 | Object Oriented*/
if (!$mysqli->set_charset("utf8")) {
        printf("Error loading character set utf8: %s\n", $mysqli->error);
        exit();
 }

LINK: http://php.net/manual/en/mysqli.set-charset.php


4

Saya mengalami masalah ini di server yang menjalankan versi PHP yang lebih lama (5.2). Saya menggunakan flag JSON_FORCE_OBJECT, dan tampaknya itu tidak didukung hingga 5.3

Jadi jika Anda menggunakan bendera itu, pastikan untuk memeriksa versi Anda!

Solusi yang tampaknya hanya mentransmisikan ke objek sebelum encoding, seperti:

json_encode((object)$myvar);

3

Pengembalian mb_detect_encodingmungkin salah:

$data = iconv('UTF-8', 'ISO-8859-1', 'La Tronche Hôpital');
var_dump(
    mb_detect_encoding($data),
    mb_detect_encoding($data, array('ISO-8859-1', 'UTF-8'))
);

Bergantung pada urutan deteksi default, yang di atas mungkin memberikan hasil yang berbeda, sehingga encoding salah dilaporkan sebagai UTF-8. ( Berikut contoh yang lebih besar .)

Sepertinya data Anda tidak dienkode sebagai UTF-8, begitu json_encodejuga yang ditampilkan false. Anda harus melihat cara mengonversi string Anda ke UTF-8 sebelum encoding JSON:

$fromEncoding = 'ISO-8859-1'; // This depends on the data

array_walk_recursive($array, function (&$value, $key, $fromEncoding) {
    if (is_string($value)) {
        $value = iconv($fromEncoding, 'UTF-8', $value);
    }
}, $fromEncoding);

3

Saya mendapatkan data dari ob_get_clean () dan memiliki masalah yang sama, tetapi solusi di atas tidak berfungsi untuk saya. Dalam kasus saya, solusinya adalah ini, mungkin itu akan membantu seseorang.

$var = mb_convert_encoding($var, 'UTF-8');

2

menggunakan utf8_encode () pada string itu memecahkan masalah saya.


1

Saya telah memperbaiki jawaban Adam Bubela. Saya benci jika blok tidak ditutup oleh {dan}. Ini lebih bersih dan Anda tidak memperkenalkan bug atau mungkin itu karena saya menggunakan Perl di masa lalu :)

<?php

class App_Updater_String_Util {    
    /**
     * Usage: App_Updater_String_Util::utf8_encode( $data );
     *
     * @param mixed $d
     * @return mixed
     * @see http://stackoverflow.com/questions/19361282/why-would-json-encode-returns-an-empty-string
     */
    public static function utf8_encode($d) {
        if (is_array($d)) {
            foreach ($d as $k => $v) {
                $d[$k] = self::utf8_encode($v);
            }
        } elseif (is_object($d)) {
            foreach ($d as $k => $v) {
                $d->$k = self::utf8_encode($v);
            }
        } elseif (is_scalar($d)) {
            $d = utf8_encode($d);
        }

        return $d;
    }
}

?>

0

Jika Anda mendapatkan data ini dari database, gunakan mysqli_set_charset($connection, "utf8");koneksi saat mendapatkan params dari database


0

masalah ini terkadang muncul - Anda tidak melewati kontrol akses header.

Dalam kasus saya jika saya telah menambahkan gema sebelum json_encode. Itu menunjukkan hasil, jika tidak, halaman kosong akan datang.

saya tambahkan

header('Access-Control-Allow-Origin: *'); 

dan masalah saya teratasi.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.