“İçerik türü: application / json; charset = utf-8 ”gerçekten mi demek?


284

REST hizmetime bir JSON gövdesi ile bir POST isteği yaptığımda Content-type: application/json; charset=utf-8ileti başlığına eklerim . Bu başlık olmadan, hizmetten bir hata alıyorum. Ben de porsiyon Content-type: application/jsonolmadan başarıyla kullanabilirsiniz ;charset=utf-8.

Tam olarak ne yapar charset=utf-8? Ben karakter kodlama belirtir ama hizmet onsuz iyi çalışıyor biliyorum. Bu kodlama, ileti gövdesinde bulunabilecek karakterleri sınırlıyor mu?



8
İlginç bir şekilde, IANA'nın application/jsonMedya Türü Kaydına göre , charsetpratikte sık sık sağlanmakla birlikte, hiç de desteklenen bir parametre görünmemektedir .
Uux

1
I know it specifies the character encoding but the service works fine without it."çalışma" her zaman "mevcut kod / yapılandırma, tek bir şey yapmak için tüm köşe vakalarını kapsayan en doğru yoldur" anlamına gelmez. Diğer koşullar altında çalışmayabilecek tüm sözleşmelere ve varsayımlara bağlıdır. Şahsen benim için her zaman olabildiğince açık olmaya çalışıyorum.
WesternGun

3
"Karakter seti" parametresi göndermek yanlış ve anlamsızdır. Bakınız RFC 8259, Bölüm 11, son cümle.
Julian Reschke

Yanıtlar:


283

Üstbilgi sadece içeriğin ne kodlandığını gösterir. İçeriğin türünü içeriğin kendisinden çıkarmak her zaman mümkün değildir, yani içeriğe bakmanız ve onunla ne yapacağınızı bilmeniz şart değildir. HTTP üstbilgileri bunun içindir, alıcıya ne tür içerikle (sözde) uğraştıklarını söylerler.

Content-type: application/json; charset=utf-8içeriği UTF-8 karakter kodlamasında kodlanan JSON biçiminde belirler. JSON için varsayılan (yalnızca?) Kodlaması UTF-8 olduğundan, kodlamayı atamak JSON için biraz gereksizdir. Bu durumda, alıcı sunucu görünüşe göre JSON ile uğraştığını bilerek mutludur ve kodlamanın varsayılan olarak UTF-8 olduğunu varsayar, bu yüzden üstbilgi ile veya üstbilgisiz çalışır.

Bu kodlama, ileti gövdesinde bulunabilecek karakterleri sınırlıyor mu?

Hayır. Üstbilgide ve gövdede istediğiniz her şeyi gönderebilirsiniz. Ancak, ikisi eşleşmezse, yanlış sonuçlar alabilirsiniz. Başlıkta içeriğin UTF-8 kodlu olduğunu belirtirseniz, ancak aslında Latin1 kodlu içerik gönderiyorsanız, alıcı Latin1 kodlu verileri UTF-8 olarak yorumlamaya çalışarak çöp verileri üretebilir. Elbette Latin1 kodlu veriler gönderdiğinizi ve bunu gerçekten yaptığınızı belirlerseniz, evet, Latin1'de kodlayabileceğiniz 256 karakterle sınırlısınız demektir.


4
Tabii ki, JSON'da Latin1 olmayan karakterleri yine de kaçış dizileri kullanarak temsil edebilirsiniz \u20AC.
dan04

31
Json standardına göre, içeriğin kodlanması için latin1 kullanmanıza izin verilmez. JSON içeriği, UTF-8, UTF-16 veya UTF-32 (büyük veya küçük endian) olsun, unicode olarak kodlanmalıdır.
Daniel Luna

20
Application / json üzerinde karakter kümesi parametresi yoktur.
Julian Reschke

7
@DanielLuna haklı, ucs application/jsondönüşüm formatlarından birinde olmalı. Ayrıca, JSON'un ilk dört baytı sınırlı olduğundan, her zaman 8, 16 veya 32 olup olmadığını ve sonlandığını söyleyebilirsiniz .
Jason Coco

4
Gerekirse, charset=utf-8güvenlik nedeniyle dahil etmek isteyebilirsiniz : github.com/shieldfy/API-Security-Checklist/issues/25
manuc66

143

@ Deceze'nin varsayılan JSON kodlamasının UTF-8 olduğu iddiasını doğrulamak için ...

Gönderen IETF RFC4627 :

JSON metni Unicode'da kodlanmalıdır. Varsayılan kodlama UTF-8'dir.

JSON metninin ilk iki karakteri her zaman ASCII karakterleri [RFC0020] olacağından, bir oktet akışının UTF-8, UTF-16 (BE veya LE) veya UTF-32 (BE veya LE) olup olmadığını belirlemek mümkündür. ilk dört oktetteki null örüntüsüne bakarak.

      00 00 00 xx  UTF-32BE
      00 xx 00 xx  UTF-16BE
      xx 00 00 00  UTF-32LE
      xx 00 xx 00  UTF-16LE
      xx xx xx xx  UTF-8

12
Her zaman JSON'u metin biçimi olarak değil, ikili biçim olarak düşünmeye yardımcı olur.
Sulthan

2
RFC4627, kök değerinin bir dize olabileceğini belirten (önceki spesifikasyonun aksine) RFC7159 tarafından kullanılmadığına göre, şimdi nasıl uygulanır? Spesifikasyon bu açıdan belirsiz ve sadece üç kodlamaya izin verildiğini söylüyor, ancak birinin bunları nasıl ayırt etmesi gerektiği değil.
Fabio Beltramini

4
@FabioBeltramini Yukarıdakiler hala geçerli olmalıdır, çünkü JSON'daki bir dize değişmez boş karakter içermeyecektir (JSON'daki null değerlerinin sayısal bir kaçış dizisiyle kodlanması gerekir "\u0000").
thomasrutter

3
Aslında UTF-16xx'daki ikinci karakter NULL değerine sahip olmayabilir, ancak diğer baytlardan kodlamayı belirlemek hala mümkün olacaktır: xx 00 00 00hala UTF-32LE ve xx 00 xx xxhala UTF-16LE, 00 xx xx xxhala UTF-16BE.
thomasrutter

20

Not IETF RFC4627 yerini aldığı IETF RFC7158 . [8.1] bölümünde @Drew tarafından belirtilen metni daha önce söyleyerek geri çekilir:

Implementations MUST NOT add a byte order mark to the beginning of a JSON text.

Yine de, geçerli bir json iki ascii karakteriyle başlayacağı için varsayım hala geçerlidir.
Laring

Bir karakter, çünkü tek bir rakam geçerli bir JSON dosyası
Nayuki

0

@Deceze ile tam olarak katılıyorum ama bu "hizmetten bir hata alıyorum" bölümünü geliştirmek istiyorum ,

Bu tür hataları http 415 olarak alıyoruz

Http 415 Desteklenmeyen Ortam türü hatası

HTTP 415 Desteklenmeyen Ortam Türü istemci hata yanıt kodu, yük biçimi desteklenmeyen bir biçimde olduğu için sunucunun isteği kabul etmeyi reddettiğini gösterir.

Biçim sorunu, isteğin belirtilen İçerik Türü veya İçerik Kodlaması nedeniyle olabilir veya verilerin doğrudan incelenmesi sonucunda ortaya çıkabilir.

Başka bir deyişle, https://stackoverflow.com/a/22643964/914284 bu örnekte görüldüğü gibi .

  • Doğru içerik türünü ayarlamamız ve doğru içerik türünü görüldüğü gibi kabul etmemiz gerekir. İçerik Türü Ekle: application / json ve Kabul Et: application / json. Aksi takdirde varsayılanı

0

Dart http's uygulama süreci bu "charset = utf-8" sayesinde baytlar, bu yüzden eminim orada birkaç uygulama bunu destekler, yanıt gelen baytları okurken "latin-1" yedek charset önlemek için. Benim durumumda, yanıt gövdesi dizesinde biçimi tamamen kaybettim, bu yüzden utf8'e elle kodlama baytları yapmak veya sunucumun API yanıtına bu üstbilgi "iç" parametresini eklemek zorundayım.


0

HttpClient kullanıyordum ve içerik türü ile yanıt başlığını geri alıyordum application/json, yabancı diller veya HttpClient ISO-8859-1 varsayılan olduğundan unicode kullanılan sembol gibi karakterleri kaybettim . Bu nedenle, olası herhangi bir sorunu önlemek için @WesternGun tarafından belirtildiği gibi mümkün olduğunca açık olun.

Sunucu nedeniyle benim için istenen başlık charset ( method.setRequestHeader("accept-charset", "UTF-8");) işlemez hiçbir yolu yoktur ve ben yanıt bayt olarak yanıt verileri almak ve UTF-8 kullanarak String dönüştürmek zorunda kaldı. Bu nedenle, açık olması ve varsayılan değer varsayımından kaçınılması önerilir.

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.