Скрамблированные умляуты с момента обновления от JSON1 до JSON2 в Perl

Я задавался вопросом, почему некоторые немецкие умлауты были скремблированы на нашей странице. Затем я узнал, что последняя версия JSON (я использую 2.07) преобразует строки другим способом, чем JSON 1.5.

Проблема здесь в том, что у меня есть хэш с строками вроде

use Data::Dumper;
my $test = {
  'fields' => 'überrascht'
};

print Dumper(to_json($test)); дает мне

$VAR1 = "{ \"fields\" : \"\x{fc}berrascht\" } "; 

Использование старого модуля с использованием

$json = JSON->new();
print Dumper ($json->to_json($test));

дает мне (правильный результат)

$VAR1 = '{"fields":[{"title":"überrascht"}]}'; 

Поэтому умлауты скремблируются с использованием нового модуля JSON 2.

Что мне нужно, чтобы их правильно исправить?

Обновление. Возможно, было плохо использовать Data :: Dumper для вывода вывода, потому что Dumper использует собственную кодировку. Ну, разница в результате от Дампера показывает, что здесь все по-другому трактуется по-разному. Возможно, лучше описать бэкэнд, как упоминал Брэд: строка json печатается с использованием Template-Toolkit, а затем назначается переменной javascript для дальнейшего использования. Правильный javascript показывает что-то вроде этого

{
    "title" : "Geändert",
},

используя новый модуль, который я получаю

{
    "title" : "Geändert",
},

Целевая страница находится в 8859-1 (latin1). Какие-либо предложения?

+1
источник поделиться
4 ответа

encode_json этого используйте encode_json. Согласно руководству он преобразует данную структуру данных Perl в кодированную двоичную строку UTF-8.

Что касается вашего обновления: если вы действительно хотите создать JSON в Latin1 (ISO-8859-1), вы можете попробовать:

to_json($test, { latin1 => 1 })

Или

JSON->new->latin1->encode($test)

Обратите внимание, что если вы дамте результат, получение \x{fc} для ü в этом случае является правильным. Я полагаю, что корень вашей проблемы заключается в том, что вы откуда-то получаете текст в формате Perl UTF-8. В этом случае необходима опция latin1 модуля JSON.

Вы также можете использовать ascii вместо latin1 как самый безопасный вариант.

Другим решением может быть указание выходной кодировки для Template-Toolkit. Я не знаю, возможно ли это. Или вы можете закодировать свой результат как Latin1 на последнем шаге перед отправкой его клиенту.

+2
источник

\x{fc} является ü, по крайней мере, в латинском-1, латинском-9 и т.д. Кроме того, ü является U+00FC в Unicode. Однако мы хотим UTF-8 (я полагаю). Самое легкое решение для получения строковых литералов UTF-8 - это сохранить исходный код Perl с помощью этой кодировки и use utf8; в верхней части вашего скрипта.

Затем, кодируя строку как JSON, получается правильный вывод:

use strict; use warnings; use utf8;
use Data::Dumper; use JSON;
print Dumper encode_json {fields => "nicht überrascht"};

encode_json предполагает UTF-8. Прочтите документацию для получения дополнительной информации.

Вывод:

$VAR1 = '{"fields":"nicht überrascht"}';

(Версия модуля JSON: 2.53)

+5
источник
my $json_text = to_json($data);

сокращается для

my $json_text = JSON->new->encode($data);

Это возвращает строку кодов кода Юникода. U + 00FC действительно является правильной кодовой точкой Unicode для "ü", поэтому выход правильный. (В качестве доказательства источником HTML для этого является "ü".)

Трудно сказать, что на самом деле был ваш исходный вывод (поскольку вы показывали символы, отличные от ASCII), поэтому трудно определить, какова ваша проблема.

Но прежде чем вывести строку, нужно сделать одно преобразование из строки кодовых точек в байты, скажем, с помощью Encode encode или encode_utf8.

my $json_cp1252 = encode('cp1252', to_json($data));

my $json_utf8 = encode_utf8(to_json($data));

Если подходящей кодировкой является UTF-8, вы также можете использовать любое из следующего:

my $json_utf8 = to_json($data, { utf8 => 1 });

my $json_utf8 = encode_json($data);

my $json_utf8 = JSON->new->utf8->encode($data);
+5
источник

Строго говоря, JSON с кодировкой Latin-1 недействителен JSON. Спецификация JSON позволяет кодировать UTF-8, UTF-16 или UTF-32.

Если вы хотите быть совместимым со стандартами или хотите, чтобы ваш JSON был совместим как с вашими текущими страницами, так и с будущими страницами на основе UTF-8, вам необходимо использовать JSON->new->utf8->encode($str). Быть строгим в отношении сгенерированного действительного JSON может сэкономить много головных болей в будущем.

Вы можете перевести UTF-8 JSON на Latin-1, используя Javascript на стороне клиента, если вам нужно, используя этот трюк.

Опция ascii также создает допустимый JSON, путем экранирования любых символов, отличных от ASCII, с использованием допустимых escape-последовательностей JSON unicode. Но вариант latin1 этого не делает, и поэтому его следует избегать ИМХО. utf8(0) следует избегать, если вы не указали кодировку при записи данных клиентам: utf8(0) отличается от опции utf8 тем, что он генерирует строки символов Perl вместо байтовых строк. Если вы делаете какие-либо ввод-вывод с использованием символьных строк без указания кодировки, Perl переводит его на лету обратно на латиницу-1. Опция utf8 генерирует необработанные байты UTF-8, которые идеально подходят для выполнения операций ввода-вывода.

+2
источник

Посмотрите другие вопросы по меткам или Задайте вопрос