2009-02-24 8 views
67

Sto scrivendo un webservice che usa JSON per rappresentare le sue risorse, e sono un po 'bloccato pensando al modo migliore di codificare il json. Leggendo json rfc (http://www.ietf.org/rfc/rfc4627.txt) è chiaro che la codifica preferita è utf-8. Ma rfc descrive anche un meccanismo di escape delle stringhe per specificare i caratteri. Presumo che questo sia generalmente usato per sfuggire ai caratteri non-ascii, rendendo in tal modo l'ASCII valido utf-8 risultante.Codifica caratteri JSON - UTF-8 è ben supportato dai browser o devo usare sequenze numeriche di escape?

Quindi diciamo che ho una stringa JSON che contiene caratteri unicode (code-point) che non sono ASCII. Il mio webservice dovrebbe solo codificarlo utf-8 e restituirlo, o dovrebbe sfuggire a tutti quei caratteri non-ascii e restituire puro ascii?

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

EDIT: Volevo chiarire che la mia preoccupazione principale su come codificare i risultati è in realtà sulla gestione del browser dei risultati. Quello che ho letto indica che i browser potrebbero essere sensibili alla codifica quando si usa JSONP in particolare. Non ho trovato alcuna informazione veramente buona sull'argomento, quindi dovrò iniziare a fare dei test per vedere cosa succede. Idealmente mi piacerebbe solo sfuggire quei pochi caratteri che sono richiesti e solo utf-8 codificare i risultati.

risposta

63

Tutti parser JSON possono gestire corretta UTF-8 altrettanto bene come le sequenze di escape numerici, come la specifica JSON richiede.

La possibilità per gli encoder JSON di utilizzare le sequenze di escape numeriche offre semplicemente una scelta più ampia. Un motivo per cui è possibile scegliere le sequenze di escape numeriche sarebbe se un meccanismo di trasporto tra il encoder e il decodificatore previsto non sia protetto da binario.

Un altro motivo potrebbe essere sequenze di escape numerici è quello di evitare che certi personaggi che appaiono nel flusso, come ad esempio <, & e ", che può essere interpretata come sequenze HTML se il codice JSON viene inserito senza sfuggire in HTML o un browser torto lo interpreta come HTML. Questo può essere una difesa contro l'HTML injection o lo scripting cross-site (nota: alcuni caratteri DEVONO essere sfuggiti in JSON, incluso " e \).

Alcuni framework, inclusa l'implementazione di PHP di JSON, sempre eseguono le sequenze di escape numeriche sul lato dell'encoder 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 decodificatori JSON hanno un problema con UTF-8.

Quindi, immagino che hai appena potrebbe decidere quale utilizzare in questo modo:

  • Basta usare UTF-8, a meno che il metodo di conservazione o il trasporto tra l'encoder e decoder non è binary-safe.

  • In caso contrario, utilizzare le sequenze di escape numeriche.

10

ASCII non c'è più. L'uso della codifica UTF-8 significa che non stai utilizzando la codifica ASCII. Che cosa si dovrebbe utilizzare il meccanismo di fuga per è quello che dice la RFC:

caratteri Tutti Unicode possono essere immessi tra le virgolette, tranne per i personaggi che devono essere sfuggito: virgoletta, invertire Solidus, e i caratteri di controllo (U + 0000 a U + 001F)

+0

Se leggi quella citazione che hai fornito vedrai che non sei obbligato a sfuggire a tutti i caratteri unicode, solo alcuni caratteri speciali. Ma ti viene richiesto di codificare i risultati (preferibilmente con utf-8). Quindi la domanda è: "Perché preoccuparsi di sfuggire a caratteri unicode normali se si utilizza la codifica utf-8". – schickb

+0

Inoltre, una stringa ascii codificata è un puro sottoinsieme di utf-8. Se uso json's escaping per tutti i caratteri non-ascii, il risultato è ascii - e quindi utf-8. Varie librerie json (come python simplejson) hanno modi per forzare i risultati ascii. Presumo per una ragione, come forse l'esecuzione nei browser. – schickb

+0

Quando si scappa l'escape di caratteri unicode normali è in contesti in cui sono metacaratteri, come le stringhe. (Il pezzo RFC che ho citato riguarda stringhe, scusate, non era chiaro a riguardo.) Non è necessario fare sempre l'output ASCII; Penserei che è più per il debug con i browser rotti. – chaos

14

Ho avuto un problema lì. Quando I JSON codifica una stringa con un carattere come "é", ogni browser restituirà lo stesso "é", ad eccezione di 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 intendevi 'utf8_encode()', http://php.net/manual/en/function.utf8-encode.php – Binyamin

+4

Se IE non riesce a decodificarlo, è un bug in qualsiasi decodificatore JSON che stai usando. Tutti i decodificatori JSON devono decodificare correttamente il modulo codificato oppure non sono un decodificatore JSON. Per quanto riguarda il tuo problema con json_decode() con é senza escape, è possibile che il testo che stai inserendo non sia UTF-8. I decodificatori JSON presumono sempre UTF-8, anche l'implementazione di PHP, anche se PHP in genere non assume UTF-8 in molte altre funzioni. Ci sono altre codifiche di carattere che possono includere un é senza escape e sembrano identici sullo schermo, ma che non sono UTF-8. La codifica in forma \ uXXXX è una soluzione a questo. – thomasrutter

+0

Solo dicendo: JSON può legalmente entrare in qualsiasi codifica Unicode (UTF-8, UTF-16 BE/LE, UTF32 BE/LE, con o senza marcatore di byte). E poiché ASCII è un sottoinsieme di UTF-8, può anche venire in ASCII. Ad esempio, i parser accettano UTF-32, non lo so. – gnasher729

0

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

3

Mi trovavo di fronte allo stesso problema. Per me funziona. Per favore controlla questo.

json_encode($array,JSON_UNESCAPED_UNICODE);