PHP декодирует и кодирует json символами unicode
-
29-10-2019 - |
Вопрос
У меня есть некоторый json, который мне нужно расшифровать, изменить, а затем закодировать, не перепутав ни одного символа.
Если у меня есть символ юникода в строке json, он не будет декодироваться.Я не уверен, почему, поскольку json.org говорит, что строка может содержать: any-Unicode-character- except-"-or-\-or- control-character
.Но это также не работает в python.
{"Tag":"Odómetro"}
Я могу использовать utf8_encode, который позволит декодировать строку с помощью json_decode, однако символ будет искажен во что-то другое.Это результат из print_r результирующего массива.Два персонажа.
[Tag] => Odómetro
Когда я снова кодирую массив, символ экранируется в ascii, что является правильным в соответствии со спецификацией json:
"Tag"=>"Od\u00f3metro"
Есть ли какой-нибудь способ, которым я могу избежать этого?json_encode не предоставляет такой опции, utf8_encode, похоже, тоже не работает.
Редактировать Я вижу, что для json_encode есть опция unescaped_unicode.Однако это работает не так, как ожидалось.О черт, это только на php 5.4.Мне придется использовать какое-нибудь регулярное выражение, так как у меня есть только 5.3.
$json = json_encode($array, JSON_UNESCAPED_UNICODE);
Warning: json_encode() expects parameter 2 to be long, string ...
Решение
Судя по всему, что вы сказали, это похоже на оригинал Odómetro
строка, с которой вы имеете дело, закодирована в ISO 8859-1, а не в UTF-8.
Вот почему я так думаю:
json_encode
созданный анализируемый вывод после того, как вы прогнали входную строку черезutf8_encode
, который преобразует ISO 8859-1 в UTF-8.- Вы действительно сказали, что получили "искаженный" вывод при использовании
print_r
после выполненияutf8_encode
, но искаженный результат, который вы получили, на самом деле является именно тем, что произошло бы при попытке проанализировать текст UTF-8 как ISO 8859-1 (- это\x63\xb3
в UTF-8, но эта последовательностьó
в стандарте ISO 8859-1. - Ваш
htmlentities
обходное решение сработало.htmlentities
необходимо знать, какая кодировка у входной строки, чтобы корректно работать.Если вы его не укажете, он предполагает стандарт ISO 8859-1.(html_entity_decode
, что сбивает с толку, по умолчанию используется UTF-8, поэтому ваш метод привел к преобразованию из ISO 8859-1 в UTF-8.) - Вы сказали, что у вас была такая же проблема в Python, которая, казалось бы, исключает PHP из числа проблем.
PHP будет использовать \uXXXX
экранирование, но, как вы заметили, это допустимый JSON.
Итак, похоже, вам нужно настроить ваше подключение к Postgres так, чтобы оно выдавало вам строки UTF-8.В руководстве по PHP указано, что вы могли бы сделать это, добавив options='--client_encoding=UTF8'
к строке подключения.Существует также вероятность того, что данные, хранящиеся в данный момент в базе данных, имеют неправильную кодировку.(Вы могли бы просто использовать utf8_encode
, но это будет поддерживать только символы, которые являются частью стандарта ISO 8859-1).
Наконец, как отмечалось в другом ответе, вам нужно убедиться, что вы объявляете правильную кодировку с заголовком HTTP или иным образом (конечно, эта конкретная проблема могла быть просто артефактом среды, в которой вы выполняли свою print_r
тестирование).
Другие советы
Я нашел следующий способ решить эту проблему ... Надеюсь, это поможет вам.
родовое слово JSON_UNESCAPED_UNICODE
был добавлен в PHP 5.4, поэтому похоже, что вам нужно обновить свою версию PHP, чтобы использовать его преимущества.Однако версия 5.4 еще не выпущена!:(
Существует альфа-кандидат на выпуск 5.4 в QA, если вы хотите поиграть на своей машине разработки.
Хакерский способ выполнения JSON_UNESCAPED_UNICODE в PHP 5.3.Действительно разочарован поддержкой PHP json.Может быть, это кому-то поможет.
родовое словопопробуйте установить на своей странице кодировку кодового кода:
родовое словоу меня работает:
родовое словоВы были близки, просто используйте utf8_decode.
Попробуйте использовать:
родовое словоДля кодирования массива, содержащего специальные символы, от ISO 8859-1 до UTF8.(Если вам не подходят utf8_encode и utf8_decode, это может быть вариант)
Все, что находится в ISO-8859-1, должно быть преобразовано в UTF8:
родовое словоКодирование должно работать после этого:
родовое слово