Hash::Ordered versus Tie::IxHash with JSON::XS encode Hash::Ordered versus Tie::IxHash with JSON::XS encode json json

Hash::Ordered versus Tie::IxHash with JSON::XS encode


The object-oriented interface of Hash::Ordered is much faster that the tied interface, but some utilities (like $json->encode) require a real hash reference

The way to get the best of both worlds is to tie a hash for use with those utilities, and use tied to extract the underlying Hash::Ordered object so that you can use the faster method calls to manipulate it

This short program demonstrates. The only slow part of this code is when the hash is passed to encode to be translated to JSON. The push call doesn't use the tied interface and remains fast

use strict;use warnings;use Hash::Ordered;use JSON::XS;my $json = JSON::XS->new->pretty;tie my %h, 'Hash::Ordered';my $oh = tied %h;$oh->push( result => { counter => 123 }, number => { num => 55 } );print $json->encode(\%h), "\n";

output

{   "result" : {      "counter" : 123   },   "number" : {      "num" : 55   }}


Use the Hash::Ordered tied interface:

my $json = JSON::XS->new;tie my %hash, "Hash::Ordered";$hash{'result'} = { 'counter' => "123" };$hash{'number1'} = { 'num' => '1' };$hash{'number2'} = { 'num' => '2' };$hash{'number3'} = { 'num' => '3' };$hash{'last'} = { 'num' => 'last' };$json->pretty(1);my $jsondata = $json->encode(\%hash);

And the JSON data you get is:

{   "result" : {      "counter" : "123"   },   "number1" : {      "num" : "1"   },   "number2" : {      "num" : "2"   },   "number3" : {      "num" : "3"   },   "last" : {      "num" : "last"   }}


The examples above work fine, but for multidimensional hashes there is an additional step needed to keep the order.

use Hash::Ordered;use JSON::XS;use Data::Dumper;use strict;use warnings;   sub ordered_hash_ref {    tie my %hash, 'Hash::Ordered';    my $oh = tied %hash;    $oh->push(@_);    return \%hash;};my $json = JSON::XS->new->pretty;tie my %h, 'Hash::Ordered';my $oh = tied %h;$oh->push(result => ordered_hash_ref(counter => 123, z => 5, s => 8),  address => ordered_hash_ref(Vorname => 'Max', Nachname => 'Mustermann', Strasse => 'Feldweg', Hausnummer => 45));my $pretty = $json->encode(\%h);print Dumper $pretty;

Output

{   "result" : {      "counter" : 123,      "z" : 5,      "s" : 8   },   "address" : {      "Vorname" : "Max",      "Nachname" : "Mustermann",      "Strasse" : "Feldweg",      "Hausnummer" : 45   }}