Gruaig has asked for the wisdom of the Perl Monks concerning the following question:

Hi Im trying to extract data from a node the json is styled as follows

{"id":241995,"name":"Georgia vs Finland","start":"2013-09-10T17:00:00.000Z","status":"paid","sport-id":15,"category-id":[146598],"markets":[],"meta-tags":[{"id":4,"name":"Soccer","type":"SPORT"},{"id":650,"name":"Qualifiers","type":"COMPETITION"},{"id":5,"name":"World Cup 2014","type":"COMPETITION"},{"id":1,"name":"Sport","type":"Root"},{"id":651,"name":"September 10th 2013","type":"DATE"}],"in-running-flag":false,"allow-live-betting":false}

The information I am trying to extract is in the meta-tag array the node which has the date and sports name in it.

So {"id":5,"name":"World Cup 2014","type":"COMPETITION"},{"id":651,"name":"September 10th 2013","type":"DATE"}

The problem is which each new api call the contents of the array change positions so if the information I wanted was in position [0] it may have moved to 3.

17 my @metatag = (); 18 19 for my $i (0..3){ 20 21 my $var1 = $decoded->{'meta-tags'}[$i]{'id'}; 22 if($var1 =~ m/([0-9a-zA-Z]{9})/ ){ 23 push @metatag => $var1; 24 my $compid = $var1; 25 $i++;

I came up with this to extract the ID tag its a horrible hack. Anyone know how I can extract the correct data everytime.?

Replies are listed 'Best First'.
Re: JSON ARRAY Problem
by Riales (Hermit) on Sep 30, 2013 at 22:21 UTC

    You should decode the JSON so you could interact with the data as Perl structures:

    use JSON; my $json = <<HERE; {"id":241995,"name":"Georgia vs Finland","start":"2013-09-10T17:00:00. +000Z","status":"paid","sport-id":15,"category-id":[146598],"markets": +[],"meta-tags":[{"id":4,"name":"Soccer","type":"SPORT"},{"id":650,"na +me":"Qualifiers","type":"COMPETITION"},{"id":5,"name":"World Cup 2014 +","type":"COMPETITION"},{"id":1,"name":"Sport","type":"Root"},{"id":6 +51,"name":"September 10th 2013","type":"DATE"}],"in-running-flag":fal +se,"allow-live-betting":false} HERE my $data = decode_json($json); my @meta_tag_ids = map { $_->{id} } @{ $data->{meta_tags} };

    EDIT: Actually, maybe I understand the problem now...you only want the IDs of the metatags that display the sport being played and the date the sport was played on, correct?

    use JSON; my $json = <<HERE; {"id":241995,"name":"Georgia vs Finland","start":"2013-09-10T17:00:00. +000Z","status":"paid","sport-id":15,"category-id":[146598],"markets": +[],"meta-tags":[{"id":4,"name":"Soccer","type":"SPORT"},{"id":650,"na +me":"Qualifiers","type":"COMPETITION"},{"id":5,"name":"World Cup 2014 +","type":"COMPETITION"},{"id":1,"name":"Sport","type":"Root"},{"id":6 +51,"name":"September 10th 2013","type":"DATE"}],"in-running-flag":fal +se,"allow-live-betting":false} HERE my $data = decode_json($json); my @interesting_meta_tag_ids = (); foreach my $metatag (@{ $data->{meta_tags} }) { my $type = $metatag->{type}; if ($type eq 'SPORT' or $type eq 'DATE') { push @interesting_meta_tag_ids, $metatag->{id}; } }

      The OP's code snippet included this line:

      my $var1 = $decoded->{'meta-tags'}[$i]{'id'};

      He's already using some JSON module to arrive at that data structure.


      Dave

        Hmm...you're right. I guess I don't understand the question then. The code I included seems to work for extracting the ID he wanted.

Re: JSON ARRAY Problem
by aaron_baugher (Curate) on Sep 30, 2013 at 22:13 UTC

    The date should be easy enough to get: grep the meta-tags array for the first item where type=>"DATE" and then take the "name" value from it. But on the other, I don't know how your program is supposed to know which type=>"COMPETITION" entry to use, so it could come up with either "Qualifiers" or "World Cup 2014" as the value. Unless there's a pattern to the data that you can count on -- the sport always comes last of any COMPETITION entries, for instance, or it's always the one with the smallest "id" value -- you're going to have a hard time picking it out programatically.

    Aaron B.
    Available for small or large Perl jobs; see my home node.

Re: JSON ARRAY Problem (category of type of id is named)
by Anonymous Monk on Oct 01, 2013 at 00:07 UTC

    I came up with this to extract the ID tag its a horrible hack. Anyone know how I can extract the correct data everytime.?

    Not sure, the format seems too dumb to correctly get the thing you want each time, both "Qualifiers" and "World Cup 2014" are of type "COMPETITION"

    Your jsontidy.pl data

    So what I would do is

    my @meata = ...; my %cat; for my $meat ( @meata ){ my( $type, $id, $name ) = @{$meat}{qw/ type id name/}; $cat{ $type }{ $id } = $name; }
    Then %category of $type of $id is $nameed

    Then %category of $type of $id is valued $name

    Then %category of $type of $id has value $name

Re: JSON ARRAY Problem
by kcott (Archbishop) on Oct 01, 2013 at 13:55 UTC

    G'day Gruaig,

    Welcome to the monastery.

    Your description of what you're trying to extract doesn't make sense. You say what you want "has the date and sports name in it". You then show two elements: the first has "name":"World Cup 2014" (which is possibly related to some sport and has a year); the second has "name":"September 10th 2013" (which clearly has a date but makes no reference to any sport).

    The code you've posted is not really of much help. It's incomplete and, as such, can't be run to reproduce what you're running; nor do we know what else it is supposed to be doing (we can only guess at the code completing the if statement and for loop). Furthermore, including line numbers (as part of the code) is also unhelpful: we'd need to remove them to run the code.

    This code shows how to access the meta-tags elements and conditionally extract them:

    #!/usr/bin/env perl use strict; use warnings; use JSON; use Data::Dumper; my $data = decode_json '{"id":241995,"name":"Georgia vs Finland","star +t":"2013-09-10T17:00:00.000Z","status":"paid","sport-id":15,"category +-id":[146598],"markets":[],"meta-tags":[{"id":4,"name":"Soccer","type +":"SPORT"},{"id":650,"name":"Qualifiers","type":"COMPETITION"},{"id": +5,"name":"World Cup 2014","type":"COMPETITION"},{"id":1,"name":"Sport +","type":"Root"},{"id":651,"name":"September 10th 2013","type":"DATE" +}],"in-running-flag":false,"allow-live-betting":false}'; my @extract; meta_wanted($_) && push @extract, $_ for @{$data->{'meta-tags'}}; print Dumper \@extract; sub meta_wanted { $_[0]->{type} eq 'SPORT' || $_[0]->{type} eq 'DATE' }

    Output:

    $VAR1 = [ { 'type' => 'SPORT', 'id' => 4, 'name' => 'Soccer' }, { 'name' => 'September 10th 2013', 'id' => 651, 'type' => 'DATE' } ];

    You'll need to define meta_wanted() how you want it: what I have there is just a guess and likely to be not what you're after.

    If you need to ask a follow-up question, please read the guidelines in "How do I post a question effectively?" before doing so.

    -- Ken

Re: JSON ARRAY Problem
by Gruaig (Initiate) on Oct 16, 2013 at 16:06 UTC
    So this is what I finally came too.
    map { my $markets = $_->{markets}; my $metatag = $_->{'meta-tags'}; my @comp = map { $_->{type} eq 'COMPETITION' ? $_->{name} : (); } @$metatag; print Dump \@comp;