Por que a função json_encode do PHP converte cadeias UTF-8 em entidades hexadecimais?


148

Eu tenho um script PHP que lida com uma grande variedade de idiomas. Infelizmente, sempre que tento usar json_encode, qualquer saída Unicode é convertida em entidades hexadecimais. Este é o comportamento esperado? Existe alguma maneira de converter a saída em caracteres UTF-8?

Aqui está um exemplo do que estou vendo:

ENTRADA

echo $text;

RESULTADO

База данни грешка.

ENTRADA

json_encode($text);

RESULTADO

"\u0411\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u0438 \u0433\u0440\u0435\u0448\u043a\u0430."

Respostas:


355

Desde o PHP / 5.4.0, existe uma opção chamada "JSON_UNESCAPED_UNICODE". Confira:

http://se2.php.net/json_encode

Portanto, você deve tentar:

json_encode( $text, JSON_UNESCAPED_UNICODE );

3
Aha. Obrigado! Eu deveria ter lido a documentação com mais cuidado. Obrigado.
David Jones

3
JSON_UNESCAPED_UNICODE foi introduzido no PHP 5.4.0 e não está disponível nas versões anteriores. Ao usá-lo nas versões anteriores, você receberá este erro: "Aviso: json_encode () espera que o parâmetro 2 seja longo, string fornecida em ...". Veja a resposta da CertaiN abaixo para a solução 5.3.
Octavian Naicu

Isso também funciona com as letras dinamarquesas Æ, æ, Ø, ø, Å, å Obrigado!
precisa saber é o seguinte

Fantástico, esta foi a resposta que eu estava procurando!
Random #

2
Você acabou de salvar minha vida. OBRIGADO.
Jon Zangitu

57

JSON_UNESCAPED_UNICODE está disponível no PHP Versão 5.4 ou posterior.
O código a seguir é para a versão 5.3.

ATUALIZADA

  • html_entity_decodeé um pouco mais eficiente que pack+ mb_convert_encoding.
  • (*SKIP)(*FAIL)pula barras invertidas e caracteres especificados por JSON_HEX_*sinalizadores.

 

function raw_json_encode($input, $flags = 0) {
    $fails = implode('|', array_filter(array(
        '\\\\',
        $flags & JSON_HEX_TAG ? 'u003[CE]' : '',
        $flags & JSON_HEX_AMP ? 'u0026' : '',
        $flags & JSON_HEX_APOS ? 'u0027' : '',
        $flags & JSON_HEX_QUOT ? 'u0022' : '',
    )));
    $pattern = "/\\\\(?:(?:$fails)(*SKIP)(*FAIL)|u([0-9a-fA-F]{4}))/";
    $callback = function ($m) {
        return html_entity_decode("&#x$m[1];", ENT_QUOTES, 'UTF-8');
    };
    return preg_replace_callback($pattern, $callback, json_encode($input, $flags));
}

1
Não deveria ser \ U, ou seja, maiúscula?
malhal

4
Boa solução para PHP <5.4;)
qdev

Eu estava procurando por três dias para encontrar esta solução para a versão 5.3, pois meu host não foi atualizado para a versão 5.4. Para mim, você é um salva-vidas e, por ser tão completo, prefiro marcar isso como resposta aceita!
Laci

Corrigido o erro quando a string continha \\ . A versão mais recente agarra \\ prioridade mais alta que \u.
mpyw

Isso deve ser adicionado na biblioteca php. Bom trabalho.
Beraki

7

Você deseja definir charset e unicode sem escape

 header('Content-Type: application/json;charset=utf-8');  
 json_encode($data,JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT);

4

Uma solução é primeiro codificar os dados e depois decodificá-los no mesmo arquivo:

$string =json_encode($input, JSON_UNESCAPED_UNICODE) ; 
echo $decoded = html_entity_decode( $string );

1

Aqui está minha solução combinada para várias versões do PHP.

Na minha empresa, estamos trabalhando com diferentes servidores com várias versões do PHP, então tive que encontrar uma solução que funcionasse para todos.

$phpVersion = substr(phpversion(), 0, 3)*1;

if($phpVersion >= 5.4) {
  $encodedValue = json_encode($value, JSON_UNESCAPED_UNICODE);
} else {
  $encodedValue = preg_replace('/\\\\u([a-f0-9]{4})/e', "iconv('UCS-4LE','UTF-8',pack('V', hexdec('U$1')))", json_encode($value));
}

Os créditos devem ir para Marco Gasi e Abu . A solução para PHP> = 5.4 é fornecida nos documentos json_encode.


0

A função raw_json_encode () acima não me resolveu o problema (por algum motivo, a função de retorno de chamada gerou um erro no meu servidor PHP 5.2.5).

Mas essa outra solução realmente funcionou.

https://www.experts-exchange.com/questions/28628085/json-encode-fails-with-special-characters.html

Os créditos devem ir para Marco Gasi . Eu apenas chamo sua função em vez de chamar json_encode ():

function jsonRemoveUnicodeSequences( $json_struct )
{ 
    return preg_replace( "/\\\\u([a-f0-9]{4})/e", "iconv('UCS-4LE','UTF-8',pack('V', hexdec('U$1')))", json_encode( $json_struct ) );
}


-2

Desde que você perguntou:

Existe alguma maneira de converter a saída em caracteres UTF-8?

Outra solução é usar utf8_encode .

Isso codificará sua string para UTF-8.

por exemplo

foreach ($rows as $key => $row) {
  $rows[$key]["keyword"] = utf8_encode($row["keyword"]);
}

echo json_encode($rows);

2
Não use isso. Conforme declarado na página de documento PHP, utf8_encode só é apropriado se a sua string original for codificada em ISO-8859-1 (Latin1). Essa não é uma função "certifique-se de que essa string seja codificada em utf-8".
Telomere

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.