Преобразовать вложенный файл данных CSV в JSON - PullRequest
0 голосов
/ 08 сентября 2018

Я пытаюсь создать функцию 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 голосов
/ 08 сентября 2018

Вот один из способов сделать это:

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-записи мы извлекаем ее идентификатор, соответствующий родительский идентификатор и статус.

Если мы уже создали узел для этого идентификатора (это происходит, если другой узел уже указал этот узел в качестве его родителя), мы просто используем существующий узел; в противном случае мы создаем новый пустой узел и сохраняем его в %nodes.

%nodes - наша вселенная узлов, проиндексированных по их идентификатору.

Мы всегда устанавливаем поля number и status. Часть 0 + предназначена для явного преобразования значений в числа (в противном случае они будут указаны в выводе JSON).

Мы добавляем наш текущий узел в список дочерних элементов его родителя (который находится в $nodes{$parent_id}{children}).

В конце мы просто напечатаем дерево под $nodes{NA}, включая его дочерние элементы, их дочерние элементы и т. Д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...