Here is my final solution to flattening JSON. I abandoned JSON Path, because keys were too complicated for headers in Excel file. I have used ➔ (space, arrow, space) to separate elements of path. Elements of path are encoded as ordinary scalar JSON data, but inside texts arrows are change to double arrows (this way they never contain single arrow with spaces around).
Here is the function for flattening:
sub flattened_json {
my ($cur_node, $top_path, $put_here) = @_;
$top_path //= [];
$put_here //= {};
if (ref $cur_node eq "HASH") {
flattened_json($$cur_node{$_}, [ @$top_path, $_ ], $pu
+t_here)
for sort keys %$cur_node;
} elsif (ref $cur_node eq "ARRAY") {
flattened_json($$cur_node[$_], [ @$top_path, $_ ], $pu
+t_here)
for 0 .. @$cur_node - 1;
} else {
$$put_here{
join " ➔ ",
map { $json_do->pretty(0)->encode($_) =~ s/
+0132;/➔➔/gr }
@$top_path
} = $json_do->pretty(0)->encode($cur_node) =~ s/ϵ
+2;/➔➔/gr;
}
return $put_here;
}
Here is the tool to replace JSON to paths with arrows json_to_paths:
#!/usr/bin/perl -CSDA
use utf8;
use Modern::Perl qw{2017};
use JSON;
use Text::Unidecode;
require "./narzędzia";
my $f = flattened_json(JSON->new->relaxed->decode(do { local $/; <STDI
+N> }));
print "$_ ➔ $$f{$_}\n" for
sort {
lc(unidecode($a =~ s/ ➔ ([0-9]+)/sprintf " ➔ %09
+d", $1/ger))
cmp
lc(unidecode($b =~ s/ ➔ ([0-9]+)/sprintf " ➔ %09
+d", $1/ger))
}
keys %$f;
and here is the tool paths_to_json to replace paths back to json:
#!/usr/bin/perl -CSDA
use utf8;
use Modern::Perl qw{2017};
use JSON;
use Text::Unidecode;
require "./narzędzia";
my $f = flattened_json(JSON->new->relaxed->decode(do { local $/; <STDI
+N> }));
print "$_ ➔ $$f{$_}\n" for
sort {
lc(unidecode($a =~ s/ ➔ ([0-9]+)/sprintf " ➔ %09
+d", $1/ger))
cmp
lc(unidecode($b =~ s/ ➔ ([0-9]+)/sprintf " ➔ %09
+d", $1/ger))
}
keys %$f;
It works like this:
# cat json.txt
{
"menu" : {
"header" : "SVG Viewer",
"items" : [
{
"id" : "Open"
},
{
"id" : "OpenNew",
"label" : "Open New"
},
null,
{
"id" : "ZoomIn",
"label" : "Zoom In"
},
{
"id" : "OriginalView",
"label" : "Original View"
}
]
}
}
# cat json.txt | ./json_to_paths
"menu" ➔ "header" ➔ "SVG Viewer"
"menu" ➔ "items" ➔ 0 ➔ "id" ➔ "Open"
"menu" ➔ "items" ➔ 1 ➔ "id" ➔ "OpenNew"
"menu" ➔ "items" ➔ 1 ➔ "label" ➔ "Open New
+"
"menu" ➔ "items" ➔ 2 ➔ null
"menu" ➔ "items" ➔ 3 ➔ "id" ➔ "ZoomIn"
"menu" ➔ "items" ➔ 3 ➔ "label" ➔ "Zoom In"
"menu" ➔ "items" ➔ 4 ➔ "id" ➔ "OriginalVie
+w"
"menu" ➔ "items" ➔ 4 ➔ "label" ➔ "Original
+ View"
# cat json.txt | ./json_to_paths | ./paths_to_json
{
"menu" : {
"header" : "SVG Viewer",
"items" : [
{
"id" : "Open"
},
{
"id" : "OpenNew",
"label" : "Open New"
},
null,
{
"id" : "ZoomIn",
"label" : "Zoom In"
},
{
"id" : "OriginalView",
"label" : "Original View"
}
]
}
}
PS. unfortunatelly perlmonks engine replaced arrows and special unicode chars with html entities... :( But I post anyway if anyone ever had the same problem