Декодировать строку JSON в Mojolicious, закодированную с помощью JSON.stringify.

Я пытаюсь отправить переменную javascript в виде строки JSON в Mojolicious, и у меня возникают проблемы с ее декодированием на стороне Perl. Моя страница использует кодировку utf-8.

Строка json (значение $self->param('routes_jsonstr')) имеет правильное значение, но Mojo::JSON не может ее декодировать. Код работает хорошо, когда нет символов utf-8. Что я делаю не так?

Javascript-код:

        var routes = [ {
            addr1: 'Škofja Loka', // string with utf-8 character
            addr2: 'Kranj'
        }];
        var routes_jsonstr = JSON.stringify(routes);
        $.get(url.on_route_change,
            {
                routes_jsonstr: routes_jsonstr
            }
        );

Перл-код:

sub on_route_change {
    my $self = shift;

    my $routes=j( $self->param('routes_jsonstr') );
    warn $self->param('routes_jsonstr');
    warn Dumper $routes;
}

Выход сервера

Wide character in warn at /opt/mojo/routes/script/../lib/Routes/Homepage.pm line 76. 
[{"addr1":"Škofja Loka","addr2":"Kranj"}] at /opt/mojo/routes/script/../lib/Routes/Homepage.pm line 76. 
$VAR1 = undef;

Последняя строка выше показывает, что декодирование строки json не сработало. Когда на стороне perl нет символов utf-8 для декодирования, все работает нормально, и $routes содержит ожидаемые данные.


person Miha Lampret    schedule 30.04.2013    source источник
comment
Вам нужно будет применить дисциплину потока :utf8 к тому месту, откуда Mojo::JSON получает свои значения параметров, но, судя по тому, что я вижу в документации Mojo::JSON на CPAN, очевидно, что он уже должен это делать. Если можете, попробуйте установить и использовать модуль JSON из CPAN; У меня были хорошие результаты, используя это для декодирования данных JSON в кодировке utf8.   -  person Aaron Miller    schedule 30.04.2013
comment
Можно ли это сделать с помощью Mojo::JSON или только с JSON.pm?   -  person Aaron Miller    schedule 30.04.2013
comment
Извините за мою неудачу с предыдущим комментарием: я заставил его работать с JSON.pm и отключил utf8. Кажется, это работает: $routes=JSON->new->utf8(0)->decode( $self->param('routes_jsonstr') ); . При включенном utf8(1) он умирает с ошибкой Wide character in subroutine entry at /opt/mojo... . Я также заменил $.get() на $.post() в javascript, но я думаю, что это не имеет никакого эффекта.   -  person Miha Lampret    schedule 30.04.2013
comment
О круто! Не возражаете, если я преобразую комментарий в ответ?   -  person Aaron Miller    schedule 30.04.2013
comment
Да, пожалуйста, конвертируйте. И спасибо за помощь!   -  person Miha Lampret    schedule 30.04.2013


Ответы (3)


Решение в стиле Mojolicious можно найти здесь: http://showmetheco.de/articles/2010/10/how-to-avoid-unicode-pitfalls-in-mojolicious.html

В Javascript я только изменил $.get() на $.post(). Обновленный и работающий код Perl теперь выглядит так:

use Mojo::ByteStream 'b';
sub on_route_change {
    my $self = shift;    
    my $routes=j( b( $self->param('routes_jsonstr') )->encode('UTF-8') );
}

Протестировано со многими разными строками utf8.

person Miha Lampret    schedule 01.05.2013

Предупреждения о широких символах появляются при печати. Это связано не с тем, как вы декодируете свой юникод, а с кодировкой STDOUT. Попробуйте use utf8::all, доступный в CPAN, который установит все ваши дескрипторы ввода-вывода в utf8. Избегание декодирования, вероятно, не решает проблему, а скорее усугубляет ее. Единственная причина, по которой это работает, заключается в том, что ваш терминал все исправляет за вас.

person Joel Berger    schedule 01.05.2013

Вы можете убрать хотя бы часть боли, избегая проблемных персонажей; см. https://stackoverflow.com/a/4901205/17389.

person ysth    schedule 01.05.2013
comment
Спасибо. При использовании пользовательской функции JSON_stringify, как это предлагается в предоставленной вами ссылке, я могу включить декодирование utf8 на стороне perl: $routes=JSON->new->utf8(1)->decode( $self->param('routes_jsonstr') ); - person Miha Lampret; 01.05.2013