Perl `JSON::XS` can produce un-canonical JSON
Sometimes you want to produce a canonical version of a data
structure in JSON - with keys sorted and no additional
whitespace. JSON::XS
promises us that we can achieve such result
with a canonical
option. It only notes that canonicalization
doesn’t work for tied hashes. But I’ve just spent half a day
debugging to learn that this is a bit more complicated.
To my complete surprise the following script fails most of the time:
use Data::Printer;
use JSON::XS;
use Test::More (tests => 1);
my $data = { date => "2018-03-13", prev_period => "2018-03-12", profile => "Desktop"};
my $pre = JSON::XS->new->utf8->canonical(1)->encode($data);
p $data;
my $post = JSON::XS->new->utf8->canonical(1)->encode($data);
is $post, $pre;
Turns out this is a problem known for 3 years with both
Data::Printer and JSON::XS
- both unfixed, except for a fork at
Cpanel-JSON-XS.
The thing is that even when you aren’t using Data::Printer
,
somebody can still break your canonical JSON representation.
I think I’ll just switch to Cpanel::JSON::XS
, there is too much
drama about hash key randomization in JSON::XS
.