Сравнение строки Unicode не выполняется в Test::Deep::cmp_deeply, когда я использую JSON::decode_json

В Perl v5.10.1 мне нужно сравнить собственные структуры perl с символами юникода с аналогичными структурами, созданными JSON::decode_json.

Пример:

use strict; use warnings;
#use utf8;
use JSON;
use Test::Deep qw(cmp_deeply);
cmp_deeply(["1"], JSON::decode_json('["1"]'), 'utf8 test 11'); # will pass
cmp_deeply(["≥"], JSON::decode_json('["1"]'), 'utf8 test ≥1'); # will fail
cmp_deeply(["1"], JSON::decode_json('["≥"]'), 'utf8 test 1≥'); # will fail
cmp_deeply(["≥"], JSON::decode_json('["≥"]'), 'utf8 test ≥≥'); # should pass

Я не могу объяснить, что происходит в последнем случае, почему две структуры не равны? Я попытался RTFM, что на самом деле не улучшило моего понимания проблемы.

Вот вывод (слегка отредактированный, так как TAP слишком многословен):

ok 1 - utf8 test 11
not ok 2 - utf8 test ≥1
# Compared $data->[0]
#    got : '≥'
# expect : '1'
not ok 3 - utf8 test 1≥
Wide character in print at Test/Builder.pm line 1698.
# Compared $data->[0]
#    got : '1'
# expect : '≥'
not ok 4 - utf8 test ≥≥
Wide character in print at Test/Builder.pm line 1698.
# Compared $data->[0]
#    got : 'â¥'
# expect : '≥'

Когда я попробовал это с use utf8;, было еще хуже (скрипт умер после 2-го теста):

ok 1 - utf8 test 11
not ok 2 - utf8 test ≥1
Wide character in print at Test/Builder.pm line 1698.
Wide character in print at Test/Builder.pm line 1698.
Wide character in print at Test/Builder.pm line 1698.
# Compared $data->[0]
#    got : '≥'
# expect : '1'
Wide character in subroutine entry at ...
# Tests were run but no plan was declared and done_testing() was not seen.

Я также попробовал обходной путь, который работает для сравнения.

use utf8;
cmp_deeply(["≥"], JSON->new->utf8(0)->decode('["≥"]'), 'utf8 test ≥≥');

... но я все еще получаю глупое предупреждение:

ok 1 - utf8 test ≥≥
Wide character in print at Test/Builder.pm line 1698.

Есть ли способ просто заставить его работать - что-то вроде use magical_unicode_solution;?

Или, возможно, мне следует проводить тесты по-другому, чтобы сделать его совместимым с Unicode?


person Aprillion    schedule 30.07.2014    source источник


Ответы (1)


Этот тест пройдет:

use Encode;
cmp_deeply( [ Encode::decode("utf8","≥") ],
    JSON::decode_json('["≥"]'), 'utf8 test ≥≥');

Декодер JSON обрабатывает ввод как кодировку UTF-8 и возвращает декодированную строку. Ваш исходный тест (тест 4) сравнивал строку в кодировке UTF-8 (два октета) с декодированной строкой (один широкий символ).

person mob    schedule 30.07.2014
comment
спасибо, это то, что я понял позже, но я надеялся избежать декодирования всей вложенной структуры вручную. В любом случае, есть ли у вас какое-либо представление о том, почему 2-й тест распечатал другой материал, чем тест 4 для того же массива? - person Aprillion; 31.07.2014
comment
и еще, почему только 2 предупреждения о Wide character in print, когда широкий символ присутствует в 3-х тестах? - person Aprillion; 31.07.2014