Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot

iterating through json decode

by Bobert1234 (Novice)
on Feb 08, 2018 at 13:30 UTC ( #1208707=perlquestion: print w/replies, xml ) Need Help??
Bobert1234 has asked for the wisdom of the Perl Monks concerning the following question:

Hi, I'm trying to iterate through a json decoded string (using JSON::PP's decode) in order to replace individual elements with corresponding perl objects (e.g. strings starting with ISODate with Time::Moment). i keep running into issues due to the structure of the json_decoded object. i'm new to per and traversing the structure to get to the parts i want to replace is a nightmare of hash/array referencing/dereferencing. here's what i have. could someone please point me to where i'm going wrong?
my $qstr = 'MONGOQUERY[ { $match: { $or : [{"prefix" : "27450500"}, {"creationDate": ISODa +te("2017-06-18T12:52:16.000")}] } }, { $project: { _id:0, prefix:1 } }, ]'; $qstr=~s/MONGOQUERY//gs; $qstr=~s/ISODate\("([^)]*?)\)/"ISODate$1/gs; #Timestamp,ISODate, NumberDecimal,NumberLong,NumberInt,Symbol my $qarrayref = JSON::PP->new->allow_nonref->relaxed->allow_barekey->l +oose->decode($qstr); my $rlimit=50; repl_mongo(\@{$qarrayref},$rlimit); sub repl_mongo{ if($_[1]>0){ open(my $fh, '>>', '/tmp/mongosample.txt'); if(ref($_[0]) eq 'ARRAY'){ foreach my $item(@{$_[0]}){ repl_mongo($item,$_[1]-1 ); } }elsif(ref($_[0]) eq 'HASH'){ foreach my $item (keys %{$_[0]}){ repl_mongo($key,$_[1]-1 ); } }else{ if(index("ISODate", $_[0]) >= 0){ $_[0] =~s/ISODate//gs; # $_[0] =Time::Moment->from_string($_[0]); } } close $fh; } } open(my $fh, '>>', '/tmp/mongosample.txt'); print $fh Dumper($qarrayref); close $fh;

Replies are listed 'Best First'.
Re: iterating through json decode
by poj (Monsignor) on Feb 08, 2018 at 14:33 UTC
    where i'm going wrong?

    Add use strict; use warnings;

    #foreach my $item (keys %{$_[0]}){ # repl_mongo($key,$_[1]-1 ); foreach my $key (keys %{$_[0]}){ repl_mongo($_[0]->{$key},$_[1]-1 ); }

    Also see index

    #if (index("ISODate",$_[0]) >= 0){ if (index($_[0],"ISODate") >= 0){

    Note to use Time::Moment->from_string($string); The string must consist of a complete date representation and time of day followed by a zone designator.

      Thank you very much poj ! that was super helpful.
Re: iterating through json decode
by Eily (Prior) on Feb 08, 2018 at 14:38 UTC

    \@{$ref} is the same as $ref, because @{$ref} accesses the array that $ref points to, and adding a \ gets the same reference.

    While accessing @_ inside a function does work, I think you should put your arguments in variable (which should be done when @_ isn't a list of similar things but each argument has its own meaning. So:

    sub repl_mongo{ my ($ref, $depth) = @_; return unless $depth; if (ref($ref) eq 'ARRAY') { ... }
    (and basically replace every use of $_[0] by $ref, and $_[1] by $depth).

    foreach my $item (keys %{$_[0]}){ repl_mongo($key,$_[1]-1 ); } The loop variable is $item, but you access $key. Do you have strict on? It should have told you about that.

    And for the date conversion, after you have found that a string starts with ISODate (that's index exactly 0 by the way) you can use substr to extract the date part (which will always be at the same positions, starting from the 8th character).

Re: iterating through json decode
by QM (Parson) on Feb 08, 2018 at 13:54 UTC
    Can you not:
    use JSON;

    Quantum Mechanics: The dreams stuff is made of

Re: iterating through json decode
by hippo (Abbot) on Feb 08, 2018 at 14:24 UTC

    Your repl_mongo looks to be a reinvention of Data::Leaf::Walker->each(). It might be simpler just to use that instead?

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1208707]
Front-paged by Corion
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others scrutinizing the Monastery: (9)
As of 2018-03-22 04:46 GMT
Find Nodes?
    Voting Booth?
    When I think of a mole I think of:

    Results (272 votes). Check out past polls.