Come mantenere json_encode () dal rilascio di stringhe con caratteri non validi

C'è un modo per impedire a json_encode() di restituire null per una string che contiene un carattere non valido (non UTF-8)?

Può essere un rompicapo rompersi in un sistema complesso. Sarebbe molto più appropriato vedere effettivamente il carattere non valido, o alless farlo omettere. Così com'è, json_encode() farà cadere silenziosamente l'intera string.

Esempio (in UTF-8):

 $string = arrays(utf8_decode("Düsseldorf"), // Deliberately produce broken string "Washington", "Nairobi"); print_r(json_encode($string)); 

Risultati in

 [null,"Washington","Nairobi"] 

Risultato desiderato:

 ["D sseldorf","Washington","Nairobi"] 

Nota : non sto cercando di far funzionare le stringhe rotte in json_encode (). Sto cercando modi per semplificare la diagnosi degli errori di codifica. Una string null non è utile per questo.

php prova a generare un errore, ma solo se distriggers display_errors . Questo è strano perché l'impostazione display_errors solo scopo di controllare se gli errori vengono printingti o less display_errors standard output, non se viene triggersto o less un errore. Voglio sottolineare che quando hai display_errors , anche se puoi vedere tutti i tipi di altri errori php, php non nasconde semplicemente questo errore, nemless lo innesca . Ciò significa che non verrà visualizzato nei log degli errori, né verranno richiamati gli eventuali error_handler personalizzati. L'errore non si verifica mai.

Ecco un codice che dimostra questo:

 error_reporting(-1);//report all errors $invalid_utf8_char = chr(193); ini_set('display_errors', 1);//display errors to standard output var_dump(json_encode($invalid_utf8_char)); var_dump(error_get_last());//nothing ini_set('display_errors', 0);//do not display errors to standard output var_dump(json_encode($invalid_utf8_char)); var_dump(error_get_last());// json_encode(): Invalid UTF-8 sequence in argument 

Quel comportmento bizzarro e sfortunato è legato a questo bug https://bugs.php.net/bug.php?id=47494 e ad alcuni altri, e non sembra che sarà mai risolto.

soluzione alternativa:

Pulire la string prima di passarla a json_encode può essere una soluzione praticabile.

 $stripped_of_invalid_utf8_chars_string = iconv('UTF-8', 'UTF-8//IGNORE', $orig_string); if ($stripped_of_invalid_utf8_chars_string !== $orig_string) { // one or more chars were invalid, and so they were stripped out. // if you need to know where in the string the first stripped character was, // then see http://stackoverflow.com/questions/7475437/find-first-character-that-is-different-between-two-strings } $json = json_encode($stripped_of_invalid_utf8_chars_string); 

http://php.net/manual/en/function.iconv.php

Il manuale dice

//IGNORE scarta silenziosamente i caratteri che sono illegali nel set di caratteri di destinazione.

Quindi, rimuovendo prima i caratteri problematici, in teoria, json_encode () non dovrebbe get nulla su cui potrebbe soffocare e fallire. Non ho verificato che l'output di iconv con il flag //IGNORE sia perfettamente compatibile con la nozione json_encodes di quali siano i caratteri utf8 validi, quindi fate attenzione all'acquirente … poiché potrebbero esserci casi limite in cui non riesce ancora. ugh, odio i problemi con i set di caratteri.

 $s = iconv('UTF-8', 'UTF-8//IGNORE', $s); 

Questo ha risolto il problema. Non sono sicuro del perché i ragazzi di php non abbiano reso la vita più semplice json_encode() .

Ad each modo l'utilizzo di quanto sopra consente a json_encode () di creare oggetti anche se i dati contengono caratteri speciali (ad esempio lettere svedesi).

È quindi ansible utilizzare il risultato in javascript senza wherer decodificare i dati nella codifica originale (con escape() , unescape() , encodeURIComponent() , decodeURIComponent() );

Lo sto usando in php (smarty):

 $template = iconv('UTF-8', 'UTF-8//IGNORE', $screen->fetch("my_template.tpl")); 

Quindi sto inviando il risultato a javascript e solo innerHTML al model pronto (html peace) nel mio documento.

Detto semplicemente che la row sopra dovrebbe essere implementata in json_encode() qualche modo per consentirgli di lavorare con qualsiasi codifica.

Questa function rimuoverà tutti i caratteri UTF8 non validi da una string:

 function removeInvalidChars( $text) { $regex = '/( [\x00-\x7F] | [\xC0-\xDF][\x80-\xBF] | [\xE0-\xEF][\x80-\xBF]{2} | [\xF0-\xF7][\x80-\xBF]{3} ) | ./x'; return preg_replace($regex, '$1', $text); } 

Lo uso dopo aver convertito un documento Excel in json, in quanto non è garantito che i documenti Excel siano in UTF8.

Non penso che ci sia un modo particolarmente sensibile di convertire caratteri non validi in un carattere visibile ma valido. È ansible sostituire i caratteri non validi con U + FFFD, che è il carattere di sostituzione Unicode girando l'espressione regolare sopra, ma che in realtà non fornisce un'esperienza utente migliore del semplice rilascio di caratteri non validi.

Devi conoscere la codifica di tutte le stringhe con cui hai a che fare, o stai entrando in un mondo di dolore.

UTF-8 è una codifica facile da usare. Inoltre, JSON è definito per utilizzare UTF-8 (http://www.json.org/JSONRequest.html). Quindi perché non usarlo?

Risposta breve: il modo per evitare che json_encode () lasci cadere le stringhe è assicurarsi che siano UTF-8 validi.

Invece di usare la function iconv, puoi usare direttamente json_encode con l'opzione JSON_UNESCAPED_UNICODE (> = PHP5.4.0)

Assicurati di inserire "charset = utf-8" nell'intestazione del tuo file php:

intestazione ('Content-Type: application / json; charset = utf-8');