PHP decodificando y codificando json con caracteres Unicode
-
29-10-2019 - |
Pregunta
Tengo algunos json que necesito decodificar, modificar y luego codificar sin estropear ningún carácter.
Si tengo un carácter Unicode en una cadena json, no se decodificará.No estoy seguro de por qué, ya que json.org dice que una cadena puede contener: any-Unicode-character- except-"-or-\-or- control-character
.Pero tampoco funciona en Python.
{"Tag":"Odómetro"}
Puedo usar utf8_encode que permitirá que la cadena se decodifique con json_decode, sin embargo, el carácter se transforma en otra cosa.Este es el resultado de print_r de la matriz de resultados.Dos personajes.
[Tag] => Odómetro
Cuando codifiqué la matriz nuevamente, el carácter escapó a ascii, lo cual es correcto según la especificación json:
"Tag"=>"Od\u00f3metro"
¿Hay alguna manera de que pueda salir de esto?json_encode no ofrece esa opción, utf8_encode tampoco parece funcionar.
Editar Veo que hay una opción unescaped_unicode para json_encode.Sin embargo, no funciona como se esperaba.Maldita sea, solo está en php 5.4.Tendré que usar algunas expresiones regulares ya que sólo tengo 5.3.
$json = json_encode($array, JSON_UNESCAPED_UNICODE);
Warning: json_encode() expects parameter 2 to be long, string ...
Solución
Por todo lo que has dicho parece el original. Odómetro
La cadena con la que estás tratando está codificada con ISO 8859-1, no con UTF-8.
He aquí por qué lo creo:
json_encode
produjo una salida analizable después de ejecutar la cadena de entrada a travésutf8_encode
, que convierte de ISO 8859-1 a UTF-8.- Dijiste que obtuviste una salida "destrozada" cuando usaste
print_r
Después de hacerutf8_encode
, pero el resultado alterado que obtuviste es en realidad exactamente lo que sucedería al intentar analizar texto UTF-8 como ISO 8859-1 (ó es\x63\xb3
en UTF-8, pero esa secuencia esó
en ISO 8859-1. - Su
htmlentities
La solución de hackear funcionó.htmlentities
Necesita saber cuál es la codificación de la cadena de entrada para que funcione correctamente.Si no especifica uno, se asume ISO 8859-1.(html_entity_decode
, de manera confusa, el valor predeterminado es UTF-8, por lo que su método tuvo el efecto de convertir de ISO 8859-1 a UTF-8). - Dijiste que tenías el mismo problema en Python, lo que parecería excluir a PHP del problema.
PHP utilizará el \uXXXX
escapando, pero como notó, este es JSON válido.
Entonces, parece que necesita configurar su conexión a Postgres para que le proporcione cadenas UTF-8.El manual de PHP indica que harías esto agregando options='--client_encoding=UTF8'
a la cadena de conexión.También existe la posibilidad de que los datos almacenados actualmente en la base de datos tengan una codificación incorrecta.(Simplemente podrías usar utf8_encode
, pero esto solo admitirá caracteres que formen parte de ISO 8859-1).
Finalmente, como se señaló en otra respuesta, debe asegurarse de declarar el juego de caracteres adecuado, con un encabezado HTTP o de otro modo (por supuesto, este problema en particular podría haber sido simplemente un artefacto del entorno donde realizó su print_r
pruebas).
Otros consejos
He encontrado la siguiente forma de solucionar este problema ... Espero que esto pueda ayudarlo.
json_encode($data,JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES);
Se agregó JSON_UNESCAPED_UNICODE
en PHP 5.4 por lo que parece que necesita actualizar su versión de PHP para aprovecharlo.Sin embargo, 5.4 aún no se ha lanzado.:(
Sin embargo, hay un candidato de lanzamiento alfa 5.4 en QA si quieres jugar en tu máquina de desarrollo.
Una forma engañosa de hacer JSON_UNESCAPED_UNICODE en PHP 5.3.Realmente decepcionado por el soporte PHP json.Quizás esto ayude a alguien más.
$array = some_json();
// Encode all string children in the array to html entities.
array_walk_recursive($array, function(&$item, $key) {
if(is_string($item)) {
$item = htmlentities($item);
}
});
$json = json_encode($array);
// Decode the html entities and end up with unicode again.
$json = html_entity_decode($rson);
intente configurar la codificación utf-8
en su página:
header('content-type:text/html;charset=utf-8');
esto me funciona:
$arr = array('tag' => 'Odómetro');
$encoded = json_encode($arr);
$decoded = json_decode($encoded);
echo $decoded->{'tag'};
$json = array('tag' => 'Odómetro'); // Original array
$json = json_encode($json); // {"Tag":"Od\u00f3metro"}
$json = json_decode($json); // Od\u00f3metro becomes Odómetro
echo $json->{'tag'}; // Odómetro
echo utf8_decode($json->{'tag'}); // Odómetro
Estuviste cerca, solo usa utf8_decode.
Intente usar:
utf8_decode() and utf8_encode
Para codificar una matriz que contiene caracteres especiales, ISO 8859-1 a UTF8.(Si utf8_encode & utf8_decode no es lo que le funciona, esta podría ser una opción)
Todo lo que está en ISO-8859-1 debe convertirse a UTF8:
$utf8 = utf8_encode('이 감사의 마음을 전합니다!'); //contains UTF8 & ISO 8859-1 characters;
$iso88591 = mb_convert_encoding($utf8, 'ISO-8859-1', 'UTF-8');
$data = $iso88591;
Codificar debería funcionar después de esto:
$encoded_data = json_encode($data);