Json_encode neden boş bir dize döndürür?


108

3 iç içe dizili basit bir php yapısına sahibim.

Belirli nesneleri kullanmıyorum ve kendime dizileri 2 iç içe döngü ile oluşturuyorum.

İşte Json'a dönüştürmek istediğim dizinin var_dump örneği.

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

Başka bir betikte benzer bir yapıya sahibim ve json_encodeiyi çalışıyor. Bu yüzden neden json_encodeburada çalışmayacağını anlamıyorum .

Düzenleme: kodlamayla ilgili bir sorun var gibi görünüyor. Ne zaman mb_detect_encodingdöner ASCII, json_encodeeserler ancak UTF8 döndüğünde, artık çalışmaz.

Edit2: şunu json_last_error()döndürür JSON_ERROR_UTF8: Hatalı biçimlendirilmiş UTF-8 karakterleri, muhtemelen yanlış kodlanmıştır .


PHP kılavuzu This function only works with UTF-8 encoded data., kodlamayla ilgili herhangi bir sorun olmaması gerektiğini söylüyor .
MahanGM

13
Kullanmaya çalışın utf8_encode()sizin üzerinde namesize dize teslim etmeden önce dizi alanları json_encode().
MahanGM

Teşekkürler ! Sorunumu çözen bu çözüme kendim geldim.
Matthieu Riegler

Evet, cevabı gördüm. İyi şanslar.
MahanGM

3
Sorunu görmek için JSON_PARTIAL_OUTPUT_ON_ERRORseçeneği kullanın (örneğin, UTF8 ile alan boş olacaktır).
Peter Krauss

Yanıtlar:


255

2 saatlik kazmadan sonra (bkz. Düzenlemeler)

Aşağıdakileri öğrendim:

  • Benim durumumda bu bir kodlama sorunu
  • mb_detect_encoding muhtemelen hatalı bir yanıt döndürür, bazı dizeler muhtemelen UTF-8 değildir
  • utf8_encode()bu dizede kullanmak sorunumu çözdü, ancak aşağıdaki nota bakın

Bir dizide bulunan tüm dizeleri UTF-8'e dönüştürmeye zorlayabilen özyinelemeli bir işlev:

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;
}

Bunu basitçe şu şekilde kullanın:

echo json_encode(utf8ize($data));

Not: utf8_encode () ISO-8859-1 dizesini belgelere göre UTF-8 olarak kodlar, bu nedenle giriş kodlamasından emin değilseniz iconv () veya mb_convert_encoding () yorumlarda ve diğer çözümlerde belirtildiği gibi daha iyi seçenekler olabilir.


4
Çözümünüz ... Ancak bir tarafı Not için teşekkürler: Değişim } else {için } else if (is_string ($d)) {; aksi takdirde her şeyi dizelere çevirirsiniz (örneğin INTa olur STRING).
Paul Peelen

3
Az önce hayatımı kurtardın. Bu işlevi bulana kadar her şeyi bitirmek üzereydim !! Teşekkür ederim.
silversunhunter

2
O NE LAN! Çözümünüzü paylaştığınız için teşekkür ederiz. Bunu anlamak için çok fazla araştırma yapmanız gerektiğini görebiliyorum ve bunu yaptığınız ve paylaştığınız için size minnettarım.
kris

1
Üç günlük hata ayıklamadan sonra, hemen seni öpebilirim.
AJB

2
Veritabanından okuyorsanız, $ conn-> set_charset ("utf8");
Andrew Briggs

36

Matthieu Riegler gerçekten iyi bir çözüm sundu ancak nesneleri işlemek için onu biraz değiştirmem gerekiyordu:

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;
}

Bir not daha: json_last_error () , json_encode () / json_encode () işlevlerinde hata ayıklamada yardımcı olabilir.


Bunun elseifyerine olması gerekmiyor else ifmu? (yani boşluk yok).
Uwe Keim

2
PHP dokümantasyonuna göre @UweKeim "elseif ve else if sadece küme parantezleri kullanıldığında tamamen aynı kabul edilecektir", yani iki nokta üst üste gösterimini kullanmadığınız sürece eşdeğer oldukları anlamına gelir, örn.if(): elseif:
Adam Bubela

1
Aferin. PHP çöptür ve sizin gibiler onu çöpe gitmekten alıkoyarlar.
Lonnie Best

else if(is_int($d)||is_bool($d)) return $d;Sonuncusundan önce bir eklemelisiniz çünkü:{"success":true, "message":"Ⲃⲟⲟ𝓵ⲉⲁⲛ ⲁⲛⲇ Ⲓⲛϯⲉ𝓰ⲉꞅ𝛓"}
David Refoua

@ Paul-Peelen @ matthieu-Riegler tavsiye Tıpkı: Değişim son elseiçin else if(is_string ($d)); aksi takdirde her şeyi dizelere çevirirsiniz (örneğin INTa olur STRING).
Bruno Serrano

30

Benim için bu sorunun cevabı charset=utf8PDO bağlantımda ayarlanıyordu .

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

2
Veya mysqli işlevlerinde: mysqli_set_charset ($ bağlantı, "utf8");
user18099

Bu benim çözümümün ipucuydu. Msqli bağlantısının biraz farklı nedeni. $mysqli->set_charset("utf8");Veritabanı işlemlerinizi yaptıktan sonra aramanız yeterli .
MaggusK

Lütfen utf8mb4son MySQL sürümlerinde kullanın . utf8eski.
Dharman

10

Adam Bubela ayrıca sorunumu çözmeme yardımcı olan gerçekten iyi bir çözüm sundu ve işte basitleştirilmiş işlev:

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
Anahtarları koruduğu için bunu beğendim.
dev0

7

PHP 5.6'da tamamen aynı sorunu yaşıyorum. Windows 7'de Open Server + Nginx kullanıyorum . Tüm karakter kümeleri UTF-8 olarak ayarlandı. Teorik olarak, resmi belgelere göre , bayrak

JSON_UNESCAPED_UNICODE

bunu çözmeli. Maalesef bu benim durumum değil. Sebebini bilmiyorum. Yukarıdaki tüm parçacıklar sorunumu çözmüyor, bu nedenle kendi uygulamamı buldum. Birine yardımcı olabileceğine inanıyorum. En azından Rus harfleri testi geçti.

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

Kabul edilen bu cevap işe yarıyor. Ancak verilerinizi MySQL'den alıyorsanız (benim gibi) daha kolay bir yol var.

Veritabanınızı açtıktan sonra, sorgulamadan önce mysqli kullanarak karakter setini aşağıdaki gibi ayarlayabilirsiniz:

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

VEYA

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

BAĞLANTI: http://php.net/manual/en/mysqli.set-charset.php


4

PHP'nin daha eski bir sürümünü (5.2) çalıştıran bir sunucuda bu sorunla karşılaştım. JSON_FORCE_OBJECT bayrağını kullanıyordum ve görünüşe göre bu 5.3'e kadar desteklenmiyor

Dolayısıyla, bu bayrağı kullanıyorsanız, sürümünüzü kontrol ettiğinizden emin olun!

Bir geçici çözüm kodlamadan önce bir nesneye yayın yapıyor gibi görünüyor, örneğin:

json_encode((object)$myvar);

3

Dönüşü mb_detect_encodingdoğru olmayabilir:

$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'))
);

Varsayılan algılama sırasına bağlı olarak, yukarıdakiler farklı sonuçlar döndürebilir, bu nedenle kodlama yanlışlıkla UTF-8 olarak rapor edilir. ( İşte daha büyük bir örnek .)

Verilerinizin UTF-8 olarak kodlanmamış olması muhtemeldir, dolayısıyla json_encodegeri dönmektedir false. JSON kodlamasından önce dizelerinizi UTF-8'e dönüştürmeye bakmalısınız:

$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

Ob_get_clean () 'den veri alıyordum ve aynı sorunu yaşadım, ancak yukarıdaki çözümler benim için çalışmıyor. Benim durumumda çözüm şuydu, belki birine yardımcı olur.

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

2

bu dizede utf8_encode () kullanmak sorunumu çözdü.


1

Adam Bubela'nın cevabını iyileştirdim. Sadece blokların {ve} tarafından kapatılmamasından nefret ediyorum. Daha temiz ve böceklere neden olmuyorsunuz ya da belki geçmişte Perl kullandım :)

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

Bu verileri bir veritabanından mysqli_set_charset($connection, "utf8");alırsanız, veritabanından parametreleri alırken bağlantılı olarak kullanın .


0

bu sorun bazen ortaya çıkar - başlık erişim denetimini geçmiyorsunuz.

Benim durumumda, json_encode'dan önce herhangi bir yankı eklediysem. Sonuç gösteriyordu aksi halde boş sayfa geliyordu.

ekledim

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

ve sorunum çözüldü.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.