Hash :: Ordered与Tie :: IxHash与JSON :: XS编码

时间:2016-06-25 12:32:12

标签: json perl hash

我尝试Hash::Ordered代替Tie::IxHash,因为它似乎更快。

虽然Tie::IxHash工作正常,但我遇到了Hash::Ordered的一些问题。关键是要对哈希值进行排序(在Perl中通常是随机的)。

use Hash::Ordered;
use JSON::XS;
use Data::Dumper;

use strict;
use warnings;

my $json = JSON::XS->new;

my $oh = Hash::Ordered->new;
$oh->push('result' => { 'counter' => "123" }, 'number' => { 'num' => '55' });

my @r = $oh->as_list;

$json->pretty(1);
my $jsondata = $json->encode(\@r);
print Dumper $jsondata;

结果很奇怪:

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

以下是Tie::IxHash的工作示例,我尝试使用Hash::Ordered获得相同的结果。

use Data::Dumper;
use Tie::IxHash;
use JSON::XS;

use strict;
use warnings;

my $json = JSON::XS->new;

my %h;
tie(%h, 'Tie::IxHash', result => { counter => "123" }, number => { num => '55' });

  $json->pretty(1);
  my $pretty_json = $json->encode(\%h);

  print Dumper $pretty_json;

输出

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

3 个答案:

答案 0 :(得分:4)

Hash::Ordered的面向对象接口比绑定接口快得多,但是某些实用程序(如$json->encode)需要真正的哈希引用

充分利用这两个世界的方法是将哈希与这些实用程序结合使用,并使用tied提取基础Hash::Ordered对象,以便您可以使用更快的方法调用操纵它

这个简短的节目演示了。此代码中唯一缓慢的部分是将哈希传递给encode以转换为JSON。 push来电不会使用绑定的界面并保持快速

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";

输出

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

答案 1 :(得分:3)

使用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);

您获得的JSON数据是:

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

答案 2 :(得分:2)

上面的示例工作正常,但对于多维哈希,还需要一个额外的步骤来保持顺序。

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;

<强>输出

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