我正在尝试创建一个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中实现此方法的正确方法是什么?
答案 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 };
有没有给根节点一个number
和status
字段。否则,它在CSV输入中就不存在,因此如果没有该行,您将得到一个仅包含children
字段的根对象。
对于每个CSV记录,我们都提取其ID,相应的父ID和状态。
如果我们已经为此ID创建了一个节点(如果另一个节点已经将该节点指定为其父节点,则会发生这种情况),我们只使用现有节点即可;否则,我们将创建一个新的空节点并将其存储在%nodes
中。
%nodes
是我们按其ID索引的节点的整个范围。
我们总是设置number
和status
字段。 0 +
部分是将值显式转换为数字(否则,它们将在JSON输出中引用)。
我们将当前节点添加到其父节点的子节点列表(在$nodes{$parent_id}{children}
中找到)。
最后,我们只需要在$nodes{NA}
下漂亮地打印树,包括其子代,子代子等等。