rurban / Cpanel-JSON-XS

Improved fork of JSON-XS

Home Page:http://search.cpan.org/dist/Cpanel-JSON-XS/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

canonical mode does not work with tied hashes

karenetheridge opened this issue · comments

I encountered this as I was testing serialization of tied hashes in my application (as I needed to preserve the tied nature, I switched to Storable here, so this bug is just a curiosity...)

Keys are not sorted when serializing tied hashes. repro case:

use strict;
use warnings;
use Cpanel::JSON::XS;
use Tie::Hash;

my %data;
@data{'a'..'z'} = (1)x26;
print Cpanel::JSON::XS->new->canonical->encode(\%data), "\n";

my %hash;
tie(%hash, 'Tie::StdHash');
@hash{'a'..'z'} = (1)x26;
print Cpanel::JSON::XS->new->canonical->encode(\%hash), "\n";

example output:

{"a":1,"b":1,"c":1,"d":1,"e":1,"f":1,"g":1,"h":1,"i":1,"j":1,"k":1,"l":1,"m":1,"n":1,"o":1,"p":1,"q":1,"r":1,"s":1,"t":1,"u":1,"v":1,"w":1,"x":1,"y":1,"z":1}
{"l":1,"s":1,"p":1,"z":1,"i":1,"j":1,"g":1,"t":1,"q":1,"x":1,"r":1,"y":1,"u":1,"w":1,"b":1,"h":1,"o":1,"f":1,"c":1,"n":1,"v":1,"e":1,"m":1,"a":1,"d":1,"k":1}

Good catch. This will definitely add some overhead as I have to store it intermediately, which goes around the nature of tied hashes, but it is a bug.

One recommended workaround is to sort it inside the tied class, as in Tie::Hash::Sorted, Tie::IxHash or any DB binding. These things can get very big, and the class should really do the sorted output by itself.

BTW it was explicitly documented that tied hashes don't support canonical. But I find it useful enough, easy enough to implement, and anyone who has a proper tied hash which is already sorted (eg DB trees), should just skip canonical

Fixed with 14bdc7b