JSON karakter kodlaması - UTF-8 tarayıcılar tarafından iyi destekleniyor mu yoksa sayısal kaçış dizileri mi kullanmalıyım?


91

Kaynaklarını temsil etmek için json kullanan bir web hizmeti yazıyorum ve json'u kodlamanın en iyi yolunu düşünürken biraz takılı kaldım. Json rfc ( http://www.ietf.org/rfc/rfc4627.txt ) okunduğunda, tercih edilen kodlamanın utf-8 olduğu açıktır. Ancak rfc ayrıca karakterleri belirlemek için bir dizge kaçış mekanizmasını tanımlar. Bunun genellikle ascii olmayan karakterlerden kaçmak için kullanılacağını ve böylece elde edilen utf-8'i geçerli ascii haline getireceğini varsayıyorum.

Diyelim ki ascii olmayan unicode karakterleri (kod noktaları) içeren bir json dizem var. Web servisim bunu sadece utf-8 kodlayıp döndürmeli mi, yoksa ascii olmayan tüm karakterlerden kaçıp saf ascii döndürmeli mi?

Tarayıcıların sonuçları jsonp veya eval kullanarak yürütebilmesini istiyorum. Bu kararı etkiler mi? Utf-8 için çeşitli tarayıcının javascript desteği hakkındaki bilgim eksik.

DÜZENLEME: Sonuçların nasıl kodlanacağına dair asıl endişemin, sonuçların tarayıcı tarafından ele alınmasıyla ilgili olduğunu açıklığa kavuşturmak istedim. Okuduklarım, tarayıcıların özellikle JSONP kullanırken kodlamaya duyarlı olabileceğini gösteriyor. Konu hakkında gerçekten iyi bir bilgi bulamadım, bu yüzden ne olacağını görmek için bazı testler yapmaya başlamam gerekecek. İdeal olarak, yalnızca gerekli olan birkaç karakterden kaçmak ve sadece utf-8 sonuçları kodlamak istiyorum.

Yanıtlar:


89

JSON belirtimi , kod çözücüler tarafından UTF-8 desteği gerektirir . Sonuç olarak, tüm JSON kod çözücüleri, sayısal kaçış dizilerini işleyebildikleri gibi UTF-8'i de işleyebilir. Bu aynı zamanda Javascript yorumlayıcıları için de geçerlidir; bu, JSONP'nin UTF-8 kodlu JSON'u da işleyeceği anlamına gelir.

JSON kodlayıcılarının sayısal kaçış dizilerini kullanma yeteneği size daha fazla seçenek sunar. Sayısal kaçış dizilerini seçmenizin bir nedeni , kodlayıcınız ile amaçlanan kod çözücü arasındaki bir aktarım mekanizmasının ikili güvenlikli olmaması olabilir.

Sayısal çıkış sıralarını kullanmak isteyebilirsiniz başka nedeni gibi akışında görünmeye belirli karakterleri, önlemektir <, &ve "JSON kodu HTML veya yanlış o yorumlayıp bir tarayıcı HTML içine kaçan olmadan yerleştirilirse HTML dizileri olarak yorumlanabilir hangi . Bu, HTML enjeksiyonuna veya siteler arası komut dosyası oluşturmaya karşı bir savunma olabilir (not: "ve dahil olmak üzere bazı karakterlerin JSON'da öncelenmesi ZORUNLUDUR \).

PHP'nin JSON uygulaması da dahil olmak üzere bazı çerçeveler, ASCII dışındaki herhangi bir karakter için kodlayıcı tarafında her zaman sayısal kaçış dizilerini yapar. Bu, sınırlı taşıma mekanizmaları ve benzerleri ile maksimum uyumluluk için tasarlanmıştır. Ancak, bu, JSON kod çözücülerinin UTF-8 ile ilgili bir sorunu olduğunun bir göstergesi olarak yorumlanmamalıdır.

Sanırım hangisini şu şekilde kullanacağınıza karar verebilirsiniz:

  • Kodlayıcı ile kod çözücü arasındaki depolama veya taşıma yönteminiz ikili olarak güvenli değilse UTF-8'i kullanın.

  • Aksi takdirde, sayısal kaçış dizilerini kullanın.


1
"tüm JSON kod çözücüleri UTF-8'i işleyebilir" Bu, tarayıcılar için geçerli olsa da, standart gerektirdiğinden, tüm yazılım kod çözme JSON'un UTF-8'i desteklediği anlamına gelmez.
Michael Mior

7
"Tüm JSON kod çözücüleri UTF-8'i işleyebilir" tam anlamıyla doğrudur. UTF-8'i kabul edemeyen bir şey bir JSON kod çözücü değildir. JSON kod çözücüsüne benzer olabilir, ancak kesinlikle değildir.
thomasrutter

Sanırım bu, kullandığınız JSON kod çözücünün hangi tanımına bağlı, ancak doğru nokta :)
Michael Mior 04

RFC 8259'un UTF-8 desteğini zorunlu olarak belirtmesinin nedeni, dünyanın standardize edildiği şeydir. Önceki eski özellikler dizeleri Unicode olarak tanımlıyordu ancak hangi kodlamayı belirtmiyordu; UTF-8'de standart hale getirilmiş uygulamalar ve güncellenen spesifikasyon bunu yansıtıyor.
thomasrutter

UTF-8 desteği, söyleyebildiğim kadarıyla belirli bir yazılım için bu RFC'de zorunlu olarak belirtilmemiştir. UTF-8'in tek sözü, kapalı bir sistemin dışında takas edilen JSON için kodlama olarak kullanılması gerektiğidir. Bu, tüm JSON kod çözücülerin (RFC'de kullanılmayan bir dil) UTF-8'i desteklemesi gerektiği anlamına gelmez.
Michael Mior

17

Orada bir sorunum vardı. "É" gibi bir karakter içeren bir dizeyi JSON kodladığımda, "\ u00e9" döndürecek IE dışında her tarayıcı aynı "é" değerini döndürecektir.

Daha sonra PHP json_decode () ile "é" bulursa başarısız olur, bu nedenle Firefox, Opera, Safari ve Chrome için json_decode () 'dan önce utf8_encode () çağırmam gerekir.

Not: Testlerimde, IE ve Firefox yerel JSON nesnelerini kullanıyor, diğer tarayıcılar json2.js kullanıyor.


10

4
IE bunu çözemezse, bu, kullandığınız JSON kod çözücüsündeki bir hatadır. Tüm JSON kod çözücülerinin kodlanmış formu başarıyla çözmesi gerekir, aksi takdirde JSON kod çözücüsü değildirler. Json_decode () ile é unescaped sorununa gelince, onu beslediğiniz metnin UTF-8 olmaması mümkündür. PHP normalde diğer birçok işlevde UTF-8'i varsaymasa da, JSON kod çözücüleri her zaman UTF-8'i varsayar. Bir é çıkış karaktersiz içerebilen ve ekranda aynı görünen, ancak UTF-8 olmayan başka karakter kodlamaları da vardır. \ UXXXX biçiminde kodlama, bunun için bir geçici çözümdür.
thomasrutter

Sadece şunu söylüyorum: JSON yasal olarak herhangi bir Unicode kodlamasında (UTF-8, UTF-16 BE / LE, UTF32 BE / LE, bayt sırası işaretleyicili veya işaretsiz) gelebilir. ASCII, UTF-8'in bir alt kümesi olduğu için ASCII'de de gelebilir. Örneğin ayrıştırıcıların UTF-32'yi kabul edip etmediğini bilmiyorum.
gnasher729

1
Bu doğru ve ayrıştırıcıların UTF-8 dışında herhangi bir şeyi desteklemesi gerekli değildir. Spesifikasyondan: "JSON metni UTF-8, UTF-16 veya UTF-32 olarak kodlanacaktır. Varsayılan kodlama UTF-8'dir ve UTF-8 ile kodlanmış JSON metinleri birlikte çalışabilecekleri anlamda birlikte çalışabilir maksimum uygulama sayısına göre başarılı bir şekilde okunmalıdır; diğer kodlamalardaki metinleri başarılı bir şekilde okuyamayan birçok uygulama vardır (UTF-16 ve UTF-32 gibi). Uygulamalar JSON metninin başına bir bayt sırası işareti EKLEMEMELİDİR. "
thomasrutter

@thomasrutter Alıntı yaptığınız özellik eski. Geçerli Spec diyor ki: " JSON metin UTF-8 kullanılarak kodlanmış MUTLAKA kapalı bir ekosistemin parçası olmayan sistemler arasında değiş tokuş JSON metni iletirken JSON Önceki özellikler UTF-8 kullanımını gerekli değil ancak büyük çoğunluğu.. JSON tabanlı yazılım uygulamalarının% 100'ü, birlikte çalışabilirliği sağlayan tek kodlama olduğu ölçüde UTF-8 kodlamasını kullanmayı seçmiştir. Uygulamalar ağ üzerinden iletilen bir iletinin başlangıcına bir bayt sırası işareti (U + FEFF) EKLEMEMELİDİR JSON metni. "
Remy Lebeau

12

ASCII artık içinde değil. UTF-8 kodlamasının kullanılması, ASCII kodlamasını kullanmadığınız anlamına gelir. Kaçış mekanizmasını kullanmanız gereken şey, RFC'nin söylediği şeydir:

Kaçılması gereken karakterler dışında tüm Unicode karakterleri tırnak işaretleri arasına yerleştirilebilir: tırnak işareti, ters katı ve kontrol karakterleri (U + 0000 - U + 001F)


1
Sağladığınız bu alıntıyı okursanız, tüm unicode karakterlerinden, yalnızca birkaç özel karakterden kaçınmanız gerekmediğini göreceksiniz. Ancak sonuçları kodlamanız gerekir (tercihen utf-8 ile). Öyleyse soru şudur: "Eğer utf-8 kodlaması yapıyorsanız neden normal unicode karakterlerinden kaçmakla uğraşıyorsunuz"?
schickb

Ayrıca, ascii kodlu bir dize, utf-8'in saf bir alt kümesidir. Tüm ascii olmayan karakterler için json's kaçışını kullanırsam, sonuç ascii - ve dolayısıyla utf-8 olur. Çeşitli json kitaplıklarının (python simplejson gibi) ascii sonuçlarını zorlamak için modları vardır. Belki tarayıcılarda çalıştırma gibi bir nedenden dolayı varsayıyorum.
schickb

Normal unicode karakterlerinden kaçmakla uğraştığınızda, dizeler gibi meta karakterlerin olduğu bağlamlardadır. (Alıntı yaptığım RFC öbeği dizelerle ilgili; üzgünüm, bu konuda net değildi.) Her zaman ASCII çıkışı yapmanız gerekmez; Bunun bozuk tarayıcılarla hata ayıklamak için daha fazla olduğunu düşünüyorum.
kaos

7

Ben de aynı problemle karşı karşıyaydım. Benim için çalışıyor. Lütfen bunu kontrol edin.

json_encode($array,JSON_UNESCAPED_UNICODE);

Soru hiçbir şekilde PHP özgü olduğunu ve sadece bahsediyor çünkü yukarıda PHP olduğunu belirtmek gerekir web hizmeti de olmayabilir PHP kullanmak (hala hatırlarsınız Okurlarımızın Eskileride ...)
ntninja

1

Json rfc ( http://www.ietf.org/rfc/rfc4627.txt ) okunduğunda, tercih edilen kodlamanın utf-8 olduğu açıktır.

Bilginize, RFC 4627 artık resmi JSON spesifikasyonu değil. 2014'te RFC 7159 tarafından kullanımdan kaldırıldı ve daha sonra 2017'de RFC 8259 tarafından kullanımdan kaldırıldı. mevcut teknik özellik olan .

RFC 8259 durumları:

8.1. Karakter kodlaması

Kapalı bir ekosistemin parçası olmayan sistemler arasında alınıp verilen JSON metni UTF-8 [RFC3629] kullanılarak kodlanmalıdır .

JSON'un önceki spesifikasyonları, JSON metni iletilirken UTF-8 kullanımını gerektirmiyordu. Bununla birlikte, JSON tabanlı yazılım uygulamalarının büyük çoğunluğu, birlikte çalışabilirliği sağlayan tek kodlama olduğu ölçüde UTF-8 kodlamasını kullanmayı seçmiştir.

Uygulamalar, ağ üzerinden iletilen bir JSON metninin başlangıcına bir bayt sırası işareti (U + FEFF) EKLEMEMELİDİR. Birlikte çalışabilirlik açısından, JSON metinlerini ayrıştıran uygulamalar, bir hata olarak ele almak yerine bir bayt sırası işaretinin varlığını göz ardı edebilir.


0

É char ile benzer bir sorun yaşadım ... Sanırım "beslediğiniz metin UTF-8 olmayabilir" yorumu muhtemelen buradaki işarete yakın. Örneğimdeki varsayılan harmanlamanın utf8'i fark edip değiştirene kadar başka bir şey olduğunu hissediyorum ... sorun veriler zaten oradaydı, bu yüzden verileri değiştirdiğimde dönüştürüp dönüştürmediğinden emin değilim, mysql'de iyi görüntüler tezgah. Sonuç olarak php json veriyi kodlamayacaktır, sadece yanlış döndürür. Sorunuma neden olan sunucu olarak hangi tarayıcıyı kullandığınızın bir önemi yok, bu karakter varsa php verileri utf8'e ayrıştırmaz. Veri mevcut olduktan sonra şemayı utf8'e dönüştürmekten mi yoksa sadece bir php hatasından mı kaynaklandığından emin değilim. Bu durumda kullanınjson_encode(utf8_encode($string));

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.