Давно хотел найти возможность создавать pretty JSON из Perl структур. Задачка-то совершенно тривиальная, на CPAN есть куча модулей как сериализовать JSON, но мне хотелось, чтобы соблюдалось два условия:
В моем текстовом редакторе настроено, что по нажатии на tab создается отступ в 4 пробела. Это достаточно стандартная настройка, очень много кода написано именно с соблюдением этого стандарта.
Но почему-то многие Perl библиотеки для работы с JSON используют в качестве отступа по умолчанию 3 пробела. Из-за этого возникает проблемы: из Perl я создаю JSON c тремя пробелами, комичу этот файл в проект, а потом когда руками хочу что-то поправить, выясняется, что тот формат, как я хочу писать, не соответствует формату в файле.
Для Perl хеша или объекта JavaScript порядок ключей не определен. Поэтому сериализатор вполне может использовать любой порядок ключей и это будет валидно. Но такой вариант очень неудобен: создали JSON с одним порядком ключей, закомитили в проект. Потом решили перегенерить JSON и повторно его создали — и, бац, все ключи в другом порядке "git diff" показывает кучу изменений, из которых сложно понять, что реально изменилось.
Поэтому хочется чтобы JSON всегда формировался одинаково, а для этого нужно определить какое-то правило, в каком порядке должны располагаться ключи. Самое простое правило — это чтобы ключи были отсортированы.
Оказалось, что решение этой задачи весьма простое. Нужно взять JSON::PP и использовать его вот таким образом:
use JSON::PP qw();
sub to_pretty_json {
my ($data) = @_;
my $json_coder = JSON::PP
->new
->pretty
->canonical
->indent_length(4)
;
my $pretty_json = $json_coder->encode($data);
return $pretty_json;
}
say to_pretty_json $data;
Вот полный текст скрипта-примера.
JSON::PP входит в дефолтную поставку Perl начиная с версии 5.14, так что такое решение будет работать из коробки на всех современных операционных системах.
20 марта 2015