Codifica dei caratteri JSON: UTF-8 è ben supportato dai browser o dovrei usare sequenze di escape numeriche?


89

Sto scrivendo un servizio web che utilizza json per rappresentare le sue risorse e sono un po 'bloccato a pensare al modo migliore per codificare json. Leggendo il json rfc ( http://www.ietf.org/rfc/rfc4627.txt ) è chiaro che la codifica preferita è utf-8. Ma l'rfc descrive anche un meccanismo di escape delle stringhe per specificare i caratteri. Presumo che questo sarebbe generalmente usato per sfuggire ai caratteri non ASCII, rendendo così il risultante ASCII valido utf-8.

Quindi diciamo che ho una stringa json che contiene caratteri Unicode (punti di codice) che non sono ascii. Il mio servizio web dovrebbe solo codificarlo utf-8 e restituirlo, o dovrebbe sfuggire a tutti quei caratteri non ASCII e restituire ASCII puro?

Vorrei che i browser fossero in grado di eseguire i risultati utilizzando jsonp o eval. Ciò influisce sulla decisione? La mia conoscenza del supporto javascript di vari browser per utf-8 è carente.

EDIT: volevo chiarire che la mia principale preoccupazione su come codificare i risultati riguarda davvero la gestione dei risultati da parte del browser. Quello che ho letto indica che i browser possono essere sensibili alla codifica quando si utilizza JSONP in particolare. Non ho trovato nessuna buona informazione sull'argomento, quindi dovrò iniziare a fare alcuni test per vedere cosa succede. Idealmente mi piacerebbe sfuggire solo a quei pochi caratteri richiesti e solo utf-8 codificasse i risultati.

Risposte:


88

La specifica JSON richiede il supporto UTF-8 da parte dei decoder. Di conseguenza, tutti i decoder JSON possono gestire UTF-8 così come possono gestire le sequenze di escape numeriche. Questo è anche il caso degli interpreti Javascript, il che significa che JSONP gestirà anche il JSON codificato UTF-8.

La possibilità per i codificatori JSON di utilizzare invece le sequenze di escape numeriche offre solo una scelta più ampia. Un motivo per cui potresti scegliere le sequenze di escape numeriche sarebbe se un meccanismo di trasporto tra il tuo codificatore e il decodificatore previsto non fosse sicuro per i binari.

Un altro motivo si consiglia di utilizzare sequenze di escape numerici è quello di evitare che certi personaggi che appaiono nel flusso, come ad esempio <, &e ", che può essere interpretata come HTML sequenze se il codice JSON viene inserito senza sfuggire in HTML o un browser torto lo interpreta come HTML . Questa può essere una difesa contro l'iniezione di HTML o lo scripting tra siti (nota: alcuni caratteri DEVONO essere sottoposti a escape in JSON, inclusi "e \).

Alcuni framework, inclusa l'implementazione di PHP di JSON, eseguono sempre le sequenze di escape numeriche sul lato del codificatore per qualsiasi carattere al di fuori di ASCII. Questo è inteso per la massima compatibilità con meccanismi di trasporto limitati e simili. Tuttavia, questo non dovrebbe essere interpretato come un'indicazione che i decoder JSON hanno un problema con UTF-8.

Quindi, immagino che potresti decidere quale usare in questo modo:

  • Usa UTF-8, a meno che il tuo metodo di memorizzazione o trasporto tra il codificatore e il decodificatore non sia sicuro per i binari.

  • Altrimenti, usa le sequenze di escape numeriche.


1
"tutti i decoder JSON possono gestire UTF-8" Anche se questo è vero per i browser, solo perché lo standard lo richiede non significa che tutto il software di decodifica JSON supporti UTF-8.
Michael Mior

7
"Tutti i decoder JSON possono gestire UTF-8" è letteralmente vero. Se qualcosa non può accettare UTF-8, non è un decodificatore JSON. Potrebbe essere simile a un decoder JSON, ma sicuramente non lo è.
thomasrutter

Immagino che dipenda dalla definizione di decoder JSON che stai utilizzando, ma è giusto che sia :)
Michael Mior

Il motivo per cui RFC 8259 specifica il supporto UTF-8 come obbligatorio è che è ciò su cui il mondo si è standardizzato. Le specifiche obsolete precedenti definivano le stringhe come Unicode ma non specificavano quale codifica; implementazioni standardizzate comunque su UTF-8 e le specifiche aggiornate lo riflettono.
thomasrutter

Il supporto UTF-8 non è specificato come obbligatorio in quella RFC per un particolare software per quanto ne so. L'unica menzione di UTF-8 è che deve essere utilizzato come codifica per JSON scambiato al di fuori di un sistema chiuso. Ciò non implica che tutti i decoder JSON (un linguaggio non utilizzato nella RFC) debbano supportare UTF-8.
Michael Mior

17

Ho avuto un problema lì. Quando codifico JSON una stringa con un carattere come "é", tutti i browser restituiranno la stessa "é", tranne IE che restituirà "\ u00e9".

Quindi con PHP json_decode (), fallirà se trova "é", quindi per Firefox, Opera, Safari e Chrome, devo chiamare utf8_encode () prima di json_decode ().

Nota: con i miei test, IE e Firefox utilizzano il loro oggetto JSON nativo, altri browser utilizzano json2.js.


10
Probabilmente volevi dire utf8_encode(), php.net/manual/en/function.utf8-encode.php
Binyamin

4
Se IE non riesce a decodificarlo, è un bug nel decoder JSON che stai utilizzando. Tutti i decodificatori JSON devono decodificare correttamente il modulo codificato o non sono un decodificatore JSON. Per quanto riguarda il tuo problema con json_decode () con é unescaped, è possibile che il testo che stai fornendo non sia UTF-8. I decoder JSON presumono sempre UTF-8, anche l'implementazione PHP, anche se PHP normalmente non assume UTF-8 in molte altre funzioni. Ci sono altre codifiche di caratteri che possono includere un é senza caratteri di escape e apparire identiche sullo schermo, ma che non sono UTF-8. La codifica nel formato \ uXXXX è una soluzione alternativa.
thomasrutter

Detto solo: JSON può legalmente entrare in qualsiasi codifica Unicode (UTF-8, UTF-16 BE / LE, UTF32 BE / LE, con o senza indicatore dell'ordine dei byte). E poiché ASCII è un sottoinsieme di UTF-8, può anche venire in ASCII. Se i parser accettano UTF-32 per esempio, non lo so.
gnasher729

1
È corretto e non è necessario che i parser supportino qualcosa di diverso da UTF-8. Dalle specifiche: "Il testo JSON DEVE essere codificato in UTF-8, UTF-16 o UTF-32. La codifica predefinita è UTF-8 e i testi JSON codificati in UTF-8 sono interoperabili nel senso che essere lette correttamente dal numero massimo di implementazioni; ci sono molte implementazioni che non possono leggere correttamente i testi in altre codifiche (come UTF-16 e UTF-32). Le implementazioni NON DEVONO aggiungere un contrassegno per l'ordine dei byte all'inizio di un testo JSON. "
thomasrutter

@thomasrutter La specifica che hai citato è vecchia. La specifica attuale dice: "Il testo JSON scambiato tra sistemi che non fanno parte di un ecosistema chiuso DEVE essere codificato utilizzando UTF-8. Le specifiche precedenti di JSON non richiedevano l'uso di UTF-8 durante la trasmissione di testo JSON. Tuttavia, la stragrande maggioranza delle implementazioni software basate su JSON hanno scelto di utilizzare la codifica UTF-8, nella misura in cui è l'unica codifica che raggiunge l'interoperabilità. Le implementazioni NON DEVONO aggiungere un byte order mark (U + FEFF) all'inizio di una trasmissione in rete Testo JSON. "
Remy Lebeau

12

ASCII non è più presente. L'uso della codifica UTF-8 significa che non stai utilizzando la codifica ASCII. Quello per cui dovresti usare il meccanismo di escape è ciò che dice la RFC:

Tutti i caratteri Unicode possono essere inseriti tra virgolette ad eccezione dei caratteri che devono essere preceduti da caratteri di escape: virgolette, solidus inverso e caratteri di controllo (da U + 0000 a U + 001F)


1
Se leggi la citazione che hai fornito, vedrai che non è necessario eseguire l'escape di tutti i caratteri Unicode, ma solo di alcuni caratteri speciali. Ma ti viene richiesto di codificare i risultati (preferibilmente con utf-8). Quindi la domanda è: "Perché preoccuparsi di sfuggire ai normali caratteri Unicode se stai codificando utf-8".
schickb

Inoltre, una stringa con codifica ASCII è un sottoinsieme puro di utf-8. Se uso l'escape di json per tutti i caratteri non ascii, il risultato è ascii - e quindi utf-8. Diverse librerie json (come python simplejson) hanno modalità per forzare i risultati ascii. Presumo per una ragione, come forse l'esecuzione nei browser.
schickb

Quando ti preoccupi di sfuggire ai normali caratteri Unicode è in contesti in cui sono metacaratteri, come le stringhe. (La parte RFC che ho citato riguarda le stringhe; mi dispiace, non era chiaro a riguardo.) Non è necessario eseguire l'output ASCII tutto il tempo; Penso che sia più per il debug con browser non funzionanti.
caos

7

Stavo affrontando lo stesso problema. Per me funziona. Per favore controlla questo.

json_encode($array,JSON_UNESCAPED_UNICODE);

Va notato che quanto sopra è PHP, poiché la domanda non è in alcun modo specifica per PHP e parla solo di servizi web che potrebbero non utilizzare PHP (come i più vecchi dei nostri lettori potrebbero ancora ricordare ...)
ntninja

1

Leggendo il json rfc ( http://www.ietf.org/rfc/rfc4627.txt ) è chiaro che la codifica preferita è utf-8.

Cordiali saluti, RFC 4627 non è più la specifica JSON ufficiale. È stato reso obsoleto nel 2014 da RFC 7159 , che è stato poi reso obsoleto nel 2017 da RFC 8259 , che è la specifica corrente.

RFC 8259 afferma:

8.1. Codifica dei caratteri

Il testo JSON scambiato tra sistemi che non fanno parte di un ecosistema chiuso DEVE essere codificato utilizzando UTF-8 [RFC3629] .

Le precedenti specifiche di JSON non richiedevano l'uso di UTF-8 durante la trasmissione di testo JSON. Tuttavia, la stragrande maggioranza delle implementazioni software basate su JSON ha scelto di utilizzare la codifica UTF-8, nella misura in cui è l'unica codifica che raggiunge l'interoperabilità.

Le implementazioni NON DEVONO aggiungere un contrassegno per l'ordine dei byte (U + FEFF) all'inizio di un testo JSON trasmesso in rete. Nell'interesse dell'interoperabilità, le implementazioni che analizzano i testi JSON POSSONO ignorare la presenza di un contrassegno dell'ordine dei byte piuttosto che considerarlo come un errore.


0

Ho avuto un problema simile con é char ... Penso che il commento "è possibile che il testo che stai fornendo non sia UTF-8" sia probabilmente vicino al segno qui. Ho la sensazione che le regole di confronto predefinite nella mia istanza fossero qualcos'altro fino a quando non mi sono reso conto e ho cambiato in utf8 ... il problema è che i dati erano già lì, quindi non sono sicuro se abbia convertito i dati o meno quando l'ho modificato, viene visualizzato bene in mysql banco di lavoro. Il risultato finale è che php non codificherà i dati in json, ma restituirà solo false. Non importa quale browser utilizzi poiché è il server che causa il mio problema, php non analizzerà i dati in utf8 se questo carattere è presente. Come ho detto non sono sicuro se è dovuto alla conversione dello schema in utf8 dopo che i dati erano presenti o solo un bug di php. In questo caso usajson_encode(utf8_encode($string));

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.