json encode () ¿cadenas no utf-8?


Así que tengo una matriz de cadenas, y todas las cadenas están utilizando la codificación ANSI predeterminada del sistema y se extrajeron de una base de datos sql. Por lo tanto, hay 256 diferentes valores posibles de bytes de caracteres (codificación de bytes individuales). ¿Hay alguna forma de que json_encode() funcione y muestre estos caracteres en lugar de tener que usar utf8_encode () en todas mis cadenas y terminar con cosas como "\u0082"?

¿O es el estándar para json?

Author: hakre, 2011-07-07

8 answers

¿Hay alguna forma de que json_encode() funcione y muestre estos caracteres en lugar de tener que usar utf8_encode() en todas mis cadenas y terminar con cosas como "\u0082"?

Si tiene una cadena codificada ANSI, usar utf8_encode() es la función incorrecta para lidiar con esto. Es necesario convertir correctamente de ANSI a UTF-8 primero. Eso ciertamente reducirá el número de secuencias de escape Unicode como \u0082 de la salida json, pero técnicamente estos las secuencias son válidas para json, no debes temerlas.

Convirtiendo ANSI a UTF-8 con PHP

json_encode funciona solo con UTF-8 cadenas codificadas . Si necesita crear json válido con éxito a partir de una cadena codificada ANSI, primero debe volver a codificarla/convertirla a UTF-8. Entonces json_encode funcionará como está documentado.

Para convertir una codificación desde ANSI (más correctamente asumo que tiene una cadena codificada Windows-1252, que es popular pero erróneamente conocido como ANSI) a UTF-8 puede hacer uso de la mb_convert_encoding() función:

$str = mb_convert_encoding($str, "UTF-8", "Windows-1252");

Otra función en PHP que puede convertir la codificación / charset de una cadena se llama iconv basado en libiconv . Puedes usarlo también:

$str = iconv("CP1252", "UTF-8", $str);

Nota sobre utf8_encode ()

utf8_encode() solo funciona para Latin-1, no para ANSI. Así que destruirás parte de tus personajes dentro de esa cadena cuando la corras a través de ella. función.


Relacionado: ¿Qué es el formato ANSI?


Para un control más detallado de lo que devuelve json_encode(), vea la lista de constantes predifinadas (dependiente de la versión de PHP, incl. PHP 5.4, algunas constantes permanecen indocumentadas y están disponibles en el código fuente solo hasta ahora).

Cambiar la codificación de un array/iterativamente (comentario PDO)

Como escribió en un comentario que tiene problemas para aplicar la función a una matriz, aquí es un ejemplo de código. Es siempre necesario primero cambiar la codificación antes de usar json_encode. Eso es solo una operación de matriz estándar, para el caso más simple de pdo::fetch() una iteración foreach:

while($row = $q->fetch(PDO::FETCH_ASSOC))
{
  foreach($row as &$value)
  {
    $value = mb_convert_encoding($value, "UTF-8", "Windows-1252");
  }
  unset($value); # safety: remove reference
  $items[] = array_map('utf8_encode', $row );
}
 31
Author: hakre,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:16:58

El estándar JSON IMPONE la codificación Unicode. De RFC4627 :

3.  Encoding

   JSON text SHALL be encoded in Unicode.  The default encoding is
   UTF-8.

   Since the first two characters of a JSON text will always be ASCII
   characters [RFC0020], it is possible to determine whether an octet
   stream is UTF-8, UTF-16 (BE or LE), or UTF-32 (BE or LE) by looking
   at the pattern of nulls in the first four octets.

           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

Por lo tanto, en el sentido más estricto, JSON codificado ANSI no sería JSON válido; esta es la razón por la que PHP impone la codificación unicode cuando usa json_encode().

En cuanto a "default ANSI", estoy bastante seguro de que sus cadenas están codificadas en Windows-1252. Se refiere incorrectamente como ANSI.

 8
Author: Andrew Moore,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-07-07 07:26:01
<?php
$array = array('first word' => array('Слово','Кириллица'),'second word' => 'Кириллица','last word' => 'Кириллица');
echo json_encode($array);
/*
return {"first word":["\u0421\u043b\u043e\u0432\u043e","\u041a\u0438\u0440\u0438\u043b\u043b\u0438\u0446\u0430"],"second word":"\u041a\u0438\u0440\u0438\u043b\u043b\u0438\u0446\u0430","last word":"\u041a\u0438\u0440\u0438\u043b\u043b\u0438\u0446\u0430"}
*/
echo json_encode($array,256);
/*
return {"first word":["Слово","Кириллица"],"second word":"Кириллица","last word":"Кириллица"}
*/
?>

JSON_UNESCAPED_UNICODE (integer) Codifique caracteres Unicode multibyte literalmente (el valor predeterminado es escapar como \uXXXX). Disponible desde PHP 5.4.0.

Http://php.net/manual/en/json.constants.php#constant.json-unescaped-unicode

 4
Author: Jenyok,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-11 10:44:55

Sí, este es el comportamiento estándar para json dentro de PHP

Si lee la documentación: http://php.net/manual/en/function.json-encode.php
Verá que solo puede funcionar con datos codificados en utf-8,

Por otro lado puedes usar el primer comentario en: http://php.net/manual/en/function.json-encode.php#104278

Y crea tu propia función de codificación/decodificación trabajando con ANSI

 1
Author: Marek Sebera,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-07-07 06:38:37

Para imprimir la palabra en español, finalmente tengo la solución como la siguiente con la aplicación de dos funciones.

$conn->set_charset("utf8");

mb_convert_encoding('THE BULLOCK ÉTAGÈRE - 3 SHELVES', "UTF-8", "Windows-1252")

Donde 'THE BULLOCK ÉTAGÃRERE - 3 SHELVES' esta cadena proviene de la base de datos, así que primero tengo object conn database object para establecer el carácter como utf8 luego he codificado la palabra en español UTF-8 a Windows-1252

 0
Author: Bhavin Thummar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-21 10:20:59

Encontré la siguiente respuesta para un problema análogo con una matriz anidada no codificada en utf-8 que tenía que codificar en json:

$inputArray = array(
    'a'=>'First item - à',
    'c'=>'Third item - é'
);
$inputArray['b']= array (
          'a'=>'First subitem - ù',
          'b'=>'Second subitem - ì'
    );
 if (!function_exists('recursive_utf8')) {
  function recursive_utf8 ($data) {
     if (!is_array($data)) {
        return utf8_encode($data);
     }
     $result = array();
     foreach ($data as $index=>$item) {
        if (is_array($item)) {
           $result[$index] = array();
           foreach($item as $key=>$value) {
              $result[$index][$key] = recursive_utf8($value);
           }
        }
        else if (is_object($item)) {
           $result[$index] = array();
           foreach(get_object_vars($item) as $key=>$value) {
              $result[$index][$key] = recursive_utf8($value);   
           }
        } 
        else {
           $result[$index] = recursive_utf8($item);
        }
     }
     return $result; 
   }
}
$outputArray =  json_encode(array_map('recursive_utf8', $inputArray ));
 -1
Author: caiofior,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-15 12:22:51
json_encode($str,JSON_HEX_TAG|JSON_HEX_AMP|JSON_HEX_APOS|JSON_HEX_QUOT);

Que convertirá ANSI basado en Windows a utf-8 y el error no será más.

 -2
Author: user3750780,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-06-18 03:43:14

Usa esto en su lugar:

<?php 
//$return_arr = the array of data to json encode 
//$out = the output of the function 
//don't forget to escape the data before use it! 

$out = '["' . implode('","', $return_arr) . '"]'; 
?>

Copie desde los comentarios del manual php json_encode. Lee siempre los comentarios. Son útiles.

 -3
Author: Raptor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-07-07 06:35:47