Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

Re: convert JSON to JSON Paths -- try not to reinvent the wheel (?)

by leszekdubiel (Scribe)
on May 29, 2020 at 15:33 UTC ( [id://11117473]=note: print w/replies, xml ) Need Help??


in reply to convert JSON to JSON Paths -- try not to reinvent the wheel (?)

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/&#1 +0132;/➔➔/gr } @$top_path } = $json_do->pretty(0)->encode($cur_node) =~ s/&#1013 +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&#281;dzia"; my $f = flattened_json(JSON->new->relaxed->decode(do { local $/; <STDI +N> })); print "$_ &#10132; $$f{$_}\n" for sort { lc(unidecode($a =~ s/ &#10132; ([0-9]+)/sprintf " &#10132; %09 +d", $1/ger)) cmp lc(unidecode($b =~ s/ &#10132; ([0-9]+)/sprintf " &#10132; %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&#281;dzia"; my $f = flattened_json(JSON->new->relaxed->decode(do { local $/; <STDI +N> })); print "$_ &#10132; $$f{$_}\n" for sort { lc(unidecode($a =~ s/ &#10132; ([0-9]+)/sprintf " &#10132; %09 +d", $1/ger)) cmp lc(unidecode($b =~ s/ &#10132; ([0-9]+)/sprintf " &#10132; %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" &#10132; "header" &#10132; "SVG Viewer" "menu" &#10132; "items" &#10132; 0 &#10132; "id" &#10132; "Open" "menu" &#10132; "items" &#10132; 1 &#10132; "id" &#10132; "OpenNew" "menu" &#10132; "items" &#10132; 1 &#10132; "label" &#10132; "Open New +" "menu" &#10132; "items" &#10132; 2 &#10132; null "menu" &#10132; "items" &#10132; 3 &#10132; "id" &#10132; "ZoomIn" "menu" &#10132; "items" &#10132; 3 &#10132; "label" &#10132; "Zoom In" "menu" &#10132; "items" &#10132; 4 &#10132; "id" &#10132; "OriginalVie +w" "menu" &#10132; "items" &#10132; 4 &#10132; "label" &#10132; "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

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11117473]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others cooling their heels in the Monastery: (6)
As of 2024-04-19 03:08 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found