在perl中构建有序JSON

在perl中构建有序JSON,json,perl,d3.js,Json,Perl,D3.js,我对JSON和D3有点不太熟悉,试图用“气泡”样式表示一些磁盘使用情况信息 基于此,初步: JSON非常简单-分层数据看起来有点像这样: 现在,我要做的是从NetApp获取一个XML格式的quotas报告 我有多个“每服务器”XML文件,大致如下: <quotas> <quota> <quota-target>/vol/vol1/qtree1</quota-target> <volume>vol1</volu

我对JSON和D3有点不太熟悉,试图用“气泡”样式表示一些磁盘使用情况信息

基于此,初步:

JSON非常简单-分层数据看起来有点像这样:

现在,我要做的是从NetApp获取一个XML格式的
quotas
报告

我有多个“每服务器”XML文件,大致如下:

<quotas>
  <quota>
    <quota-target>/vol/vol1/qtree1</quota-target>
    <volume>vol1</volume>
    <disk-used>554444</disk-used>
    <disk-limit>2000000</disk-limit>
  </quota>
  <quota>
    <quota-target>/vol/vol1/qtree2</quota-target>
    <volume>vol1</volume>
    <disk-used>1235655</disk-used>
    <disk-limit>2000000</disk-limit>
  </quota>
  <quota>
    <quota-target>/vol/vol2/qtree1</quota-target>
    <volume>vol2</volume>
    <disk-used>987664</disk-used>
    <disk-limit>2000000</disk-limit>
  </quota>
</quotas>
这是广泛的工作,并产生我漂亮的图片

但是我有两个问题:

每次运行JSON的顺序都会发生变化,因为我使用的是散列。虽然不是一个表演的阻碍-有没有一种方法可以在JSON输出中强制执行命令?(不一定只是按字母顺序“排序”)

类似地,我正在研究如何插入当前不存在的“卷”级节点,因为我正在创建新的匿名哈希以插入
foreach
循环的每一层的
children
。这感觉有点笨重,但我想的是:

  • 使用
    get_xpath('//volume')
    提取卷列表并对其进行唯一化
  • 每个卷迭代
    查找匹配的子节点(是否有
    xpath
    表达式来指定子值?)
  • 或者创建散列的“暂存”散列,然后将其“合并”到JSON中的
    子类中
    
有谁有更好的建议吗

我可以很容易地创建所需结构的散列

$stuff{$site}{$server}{$volume}{$qtree} = $size; 
但随后必须将其转换为适当的JSON(我认为总体而言,这可能是一种更好的方法)

有没有办法在JSON输出中强制执行命令

是的,使用数组而不是对象。JSON对象是无序的

对象是一组无序的名称/值对

但似乎您已经在为列表使用数组了


也许您希望能够执行diff,在这种情况下,JSON.pm提供了一种粗略的方法,以
sort\u by
的形式指定键。如果您想执行差异,则此功能非常有用。

如果您只想通过哈希键“强制”排序,您可以使用“规范”功能,如前所述。

您的问题似乎包含多个问题。
#!/usr/bin/env perl
use strict;
use warnings;
use XML::Twig;
use JSON;

my %sites = (
    'site1' => [qw ( servera serverb )],
    'site2' => [qw ( s2serverc s2serverd)],
);

my $data;
$data->{'name'} = "quotas";
foreach my $sitename ( keys %sites ) {
    my $site = { 'name' => $sitename };
    push( @{ $data->{'children'} }, $site );
    foreach my $server ( @{ $sites{$sitename} } ) {
        my $server = { 'name' => $server };
        push( @{ $site->{'children'} }, $server );

        $twig->parsefile("$server.quotas.xml");
        foreach my $quota ( $twig->get_xpath('//quota') ) {
            push(
                @{ $server->{'children'} },
                {   'name' => $quota->first_child_text('quota-target'),
                    'size' => $quota->first_child_text('disk-used')
                }
                )

        }
    }
}

open( my $output, ">", "quotas.json" ) or die $!;
print {$output} to_json( $data, { 'pretty' => 1 } );
close($output);
$stuff{$site}{$server}{$volume}{$qtree} = $size;