Cosa significa "Content-type: application / json; charset = utf-8 "significa davvero?


284

Quando invio una richiesta POST con un corpo JSON al mio servizio REST, includo Content-type: application/json; charset=utf-8nell'intestazione del messaggio. Senza questa intestazione, ricevo un errore dal servizio. Posso anche usare con successo Content-type: application/jsonsenza il;charset=utf-8 porzione.

Che cosa fa esattamente charset=utf-8? So che specifica la codifica dei caratteri, ma il servizio funziona bene senza di essa. Questa codifica limita i caratteri che possono essere nel corpo del messaggio?



8
Curiosamente, secondo la application/jsonregistrazione del tipo di supporto IANA , non sembra esserci alcun charsetparametro supportato , anche se spesso viene fornito in pratica.
Uux,

1
I know it specifies the character encoding but the service works fine without it."lavorare" non significa sempre "il codice / configurazione esistente è il modo più corretto che copre tutti i casi angolari per fare una cosa". Dipende da tutte le convenzioni e ipotesi che potrebbero non funzionare in altre circostanze. Personalmente, cerco sempre di essere il più esplicito possibile.
WesternGun

3
L'invio di un parametro "charset" non è corretto e privo di significato. Vedi RFC 8259, Sezione 11, ultima frase.
Julian Reschke,

Risposte:


283

L'intestazione indica semplicemente in che cosa è codificato il contenuto. Non è necessariamente possibile dedurre il tipo di contenuto dal contenuto stesso, vale a dire che non si può necessariamente solo guardare il contenuto e sapere cosa farne. Ecco a cosa servono le intestazioni HTTP, dicono al destinatario con quale tipo di contenuto stanno (presumibilmente) trattano.

Content-type: application/json; charset=utf-8indica che il contenuto deve essere in formato JSON, codificato nella codifica dei caratteri UTF-8. La designazione della codifica è in qualche modo ridondante per JSON, poiché la codifica predefinita (solo?) Per JSON è UTF-8. Quindi in questo caso il server ricevente sembra essere felice di sapere che ha a che fare con JSON e presume che la codifica sia UTF-8 per impostazione predefinita, ecco perché funziona con o senza l'intestazione.

Questa codifica limita i caratteri che possono essere nel corpo del messaggio?

No. Puoi inviare tutto ciò che vuoi nell'intestazione e nel corpo. Ma, se i due non corrispondono, potresti ottenere risultati errati. Se si specifica nell'intestazione che il contenuto è codificato UTF-8 ma in realtà si sta inviando contenuto codificato Latin1, il destinatario può produrre dati inutili, cercando di interpretare i dati codificati Latin1 come UTF-8. Se ovviamente specifichi che stai inviando dati con codifica Latin1 e lo stai effettivamente facendo, allora sì, sei limitato ai 256 caratteri che puoi codificare in Latin1.


4
Naturalmente, in JSON potresti comunque rappresentare personaggi non latini1 usando sequenze di escape come \u20AC.
dan04,

31
Secondo lo standard per json, in realtà non ti è permesso usare latin1 per la codifica dei contenuti. Il contenuto JSON deve essere codificato come Unicode, sia UTF-8, UTF-16 o UTF-32 (big o little endian).
Daniel Luna,

20
Non esiste alcun parametro charset su application / json.
Julian Reschke,

7
@DanielLuna ha ragione, application/jsondeve essere in uno dei formati di trasformazione ucs. Inoltre, poiché i primi quattro byte di JSON sono limitati, puoi sempre dire se sono 8, 16 o 32 e la sua endian-ness.
Jason Coco,

4
Evento se è ridondante che potresti voler includere charset=utf-8per motivi di sicurezza: github.com/shieldfy/API-Security-Checklist/issues/25
manuc66

143

Per confermare l'affermazione di @ deceze secondo cui la codifica JSON predefinita è UTF-8 ...

Da IETF RFC4627 :

Il testo JSON DEVE essere codificato in Unicode. La codifica predefinita è UTF-8.

Poiché i primi due caratteri di un testo JSON saranno sempre caratteri ASCII [RFC0020], è possibile determinare se un flusso di ottetti è UTF-8, UTF-16 (BE o LE) o UTF-32 (BE o LE) osservando il modello di null nei primi quattro ottetti.

      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
Aiuta sempre a pensare a JSON come formato binario, non in formato testo.
Sulthan,

2
Ora che RFC4627 è stato obsoleto da RFC7159, in cui si afferma che il valore radice può essere una stringa (in contrasto esplicito con le specifiche precedenti), come viene ora implementato? La specifica è vaga a questo proposito, e dice solo che sono consentite tre codifiche, ma non come si dovrebbe differenziarle.
Fabio Beltramini,

4
@FabioBeltramini Quanto sopra dovrebbe ancora essere valido, poiché una stringa in JSON non conterrà alcun carattere nullo letterale (i valori nulli in JSON dovrebbero essere codificati con una sequenza numerica di escape, ad esempio "\u0000").
thomasrutter,

3
In realtà il secondo carattere in UTF-16xx potrebbe non avere un NULL in quel caso, ma sarà comunque possibile determinare la codifica dagli altri byte: xx 00 00 00è ancora UTF-32LE ed xx 00 xx xxè ancora UTF-16LE, 00 xx xx xxè ancora UTF-16BE.
thomasrutter,

20

Si noti che IETF RFC4627 è stato sostituito da IETF RFC7158 . Nella sezione [8.1] ritrae il testo citato in precedenza da @Drew dicendo:

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

L'ipotesi è ancora valida, poiché qualsiasi json valido inizierà comunque con due caratteri ASCII.
Larsing,

Un personaggio, perché un singolo numero è un file JSON valido
Nayuki,

0

Sono esattamente d'accordo con @deceze ma voglio sviluppare questo "Ricevo un errore dal servizio" parte della domanda ,

Stiamo ricevendo questo tipo di errori come http 415

Http 415 Errore di tipo di supporto non supportato

Il codice di risposta dell'errore client Tipo supporto non supportato HTTP 415 indica che il server rifiuta di accettare la richiesta perché il formato del payload è in un formato non supportato.

Il problema del formato potrebbe essere dovuto al tipo di contenuto o alla codifica del contenuto indicati dalla richiesta o al controllo diretto dei dati.

In altre parole, come visto in https://stackoverflow.com/a/22643964/914284 questo esempio.

  • Dobbiamo impostare il tipo di contenuto corretto e dobbiamo accettare il tipo di contenuto corretto come visto Aggiungi tipo di contenuto: application / json e Accetta: application / json. Altrimenti assumerà il valore predefinito

0

Dardeggia il processo di implementazione di http con i byte grazie a "charset = utf-8", quindi sono sicuro che diverse implementazioni là fuori lo supportano, per evitare il set di fallback "latin-1" durante la lettura dei byte dalla risposta. Nel mio caso, perdo totalmente il formato sulla stringa del corpo della risposta, quindi devo eseguire la codifica manuale dei byte in utf8 o aggiungere il parametro "interno" dell'intestazione sulla risposta API del mio server.


0

Stavo usando HttpClient e ho recuperato l'intestazione della risposta con il tipo di contenuto di application/json, ho perso caratteri come lingue straniere o simboli che utilizzavano unicode poiché HttpClient è predefinito ISO-8859-1 . Quindi, sii il più esplicito possibile, come indicato da @WesternGun per evitare ogni possibile problema.

Non c'è modo di gestire che a causa del server non gestisce charset ( method.setRequestHeader("accept-charset", "UTF-8");) dell'intestazione richiesto per me e ho dovuto recuperare i dati di risposta come byte di disegno e convertirli in String usando UTF-8. Pertanto, si consiglia di essere espliciti ed evitare l'assunzione del valore predefinito.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.