将嵌套的CSV数据文件转换为JSON

时间:2018-09-07 23:38:45

标签: json perl csv

我正在尝试创建一个Perl函数,该函数会将特殊格式的CSV转换为JSON。

我有一个CSV文件,其中每一行都具有以下格式

child_number,parent_number,status

根父级(无父级)具有parent_number = NA

我的目标是像这样转换为JSON格式

{
number:
status:
children: [
    {
        number: 
        status: 
        children: [
            {
                number: 
                status:
            }
        ]
    },
        number: 
        status: 
        children: [
            {
                number: 
                status:
            }
        ]
     ]
}

我将CSV文件的内容插入到数组中,发现没有父行的行

foreach my $line ( @csv_arr ) {
    ($child, $perent, $status) = split(/,/,$line);
    last if ( $perent eq "NA" );
}

return 0 unless($perent eq "NA");

我想为每个$perent获取子代并将其插入数据结构。我可以使用以下

push @{ $json_struct->{usage} }, {
    number   => $perent,
    children => getChildren(),
};

...

my @json_arr = JSON::PP->new->encode($json_struct);

为了更好地解释自己,请考虑以下示例

> cat ./csv_file
7,5,0
5,NA,0
3,5,1
> cat ./json_file
{
  number: NA
  status: 0
  children: [
      {
          number: 5
          status: 0
          children: [
              {
                  number: 3
                  status: 1
              },
              {
                  number: 7
                  status: 0
              }
          ]
      }
  ]
}

这些是实际运行后CSV文件的内容

7696,44641,0                                                                                                
44654,44641,0                                                                                              
44646,44641,0                                                                                               
44644,44641,0                                                                                               
44651,44649,0                                                                                               
7700,44641,0
7691,44641,0
44657,44641,0
7699,7698,0
7692,44641,0
44650,44649,0
44661,44660,0
44656,44654,1
44659,44641,0
44648,44646,0
7695,7694,0
44662,44660,0
44641,NA,0
7701,7700,0
7698,44641,0
44653,44651,1
44645,44644,0
44647,44646,0
44649,44641,0
44660,44641,0
7697,7696,0
7689,7688,0
7694,44641,0
44658,44657,1
7693,44641,0
7688,44641,0

在Perl中实现此方法的正确方法是什么?

1 个答案:

答案 0 :(得分:1)

这里是一种方法:

use strict;
use warnings;
use JSON::PP ();

my %nodes;
$nodes{NA} = { number => 'NA', status => 0 };

while (my $line = readline DATA) {
    chomp $line;
    my ($id, $parent_id, $status) = split /,/, $line;
    my $node = $nodes{$id} //= {};
    $node->{number} = 0 + $id;
    $node->{status} = 0 + $status;
    push @{ $nodes{$parent_id}{children} }, $node;
}

my $jsonpp = JSON::PP->new->pretty->canonical;
print $jsonpp->encode($nodes{NA});

__DATA__
7,5,0
5,NA,0
3,5,1

输出:

{
   "children" : [
      {
         "children" : [
            {
               "number" : 7,
               "status" : 0
            },
            {
               "number" : 3,
               "status" : 1
            }
         ],
         "number" : 5,
         "status" : 0
      }
   ],
   "number" : "NA",
   "status" : 0
}

唯一原因

$nodes{NA} = { number => 'NA', status => 0 };

有没有给根节点一个numberstatus字段。否则,它在CSV输入中就不存在,因此如果没有该行,您将得到一个仅包含children字段的根对象。

对于每个CSV记录,我们都提取其ID,相应的父ID和状态。

如果我们已经为此ID创建了一个节点(如果另一个节点已经将该节点指定为其父节点,则会发生这种情况),我们只使用现有节点即可;否则,我们将创建一个新的空节点并将其存储在%nodes中。

%nodes是我们按其ID索引的节点的整个范围。

我们总是设置numberstatus字段。 0 +部分是将值显式转换为数字(否则,它们将在JSON输出中引用)。

我们将当前节点添加到其父节点的子节点列表(在$nodes{$parent_id}{children}中找到)。

最后,我们只需要在$nodes{NA}下漂亮地打印树,包括其子代,子代子等等。