0

Preface: I'm "new" to Perl, meaning before 3 days ago I had not written anything in Perl since dinosaurs roamed the earth. Yes, I RTFM, but still new at this.

So, I'm trying to parse a response from a call to the Twitter API. Parsing the response using TT templates works well on the view side for a single call to the Twitter API (via the awesome Net::Twitter::Lite). But now I need to make two calls, somehow extract two Perl Arrays of Strings from this data, zip them, then uniq them as I'm looking for their intersection.

My response from this call:

my @response = $nt->friends_list({ screen_name => 'someguyiknow' }); #not an actual screen name!

Looks like this when I just print it, as expected: HASH(0x7fb5093bf458)

If I print Dumper(\n@response), I also get what I would expect, an Array of Hash objects with beautifully formatted JSON all pretty-printed. (If I use $response, same result.)

So I tried to drill into this Hash:

foreach my $key ( keys %data )
{
  print "key: $key, value: $data{$key}\n";
}

This gives key: HASH(0x7fb3aa516968), value:

Value, naturally, blank b/c a Hash is not a key.

So I drilled deeper:

foreach my $key ( keys %data )
{
  my %key = $key;
  foreach my $k ( keys %key )
  {
     print "key: $k, value: $key{$k}\n"
  }    
}

And again got key: HASH(0x7fa7a20081f8), value:

So I decided to take a different approach and use the JSON parsing methods.

However, any variation on this theme (and believe you me, I've tried A TON of variations - inner loops, weird stuff from various SO messages, etc.):

my @json = from_json($response);

Which all produce this wonderfully cryptic error: "malformed JSON string, neither tag, array, object, number, string or atom, at character offset 0"

Yes, I searched the cryptic error message!! Alas, no answer that helped there.

So! I decided maybe it needed to go to_json:

my $json = to_json $response;
print "$json\n";

Wheeee! The json comes out, all pretty-printed. Except I get another one of these

"Wide character in print at line 41", which is: print "$json\n";

The JSON looks something like this:

{ "previous_cursor_str" : "0", "next_cursor_str" : "1446632917268460946", "previous_cursor" : 0, "next_cursor" : 1446632917268460946, "users" : [

What I need is the data coming in the "users" field.

So I just need a Perl scalar, right?

my $perl_scalar = from_json($json);
print "$perl_scalar\n";

Which produces this cryptic error: "Wide character in subroutine entry"

When searched that error message also yields very little fruit. Apparently 'bug not feature', according to one guy. sigh.

So I tried to just get the values from my json Hash:

print "$json->{users}{screen_name}\n";

That gives me "Can't use string ("{ "previous_cursor_str" : "0""...) as a HASH ref while "strict refs""

Which, not surprisingly, doesn't turn up any search results. In case it would work I also tried to print $json.user.screen_name. No, of course it would not be that easy.

Basically I now have a proper json object, as far as I can tell. I just need to parse through it and collect the screen_name fields into a Perl scalar as strings. This does not seem unreasonable yet I'm finding it completely impossible.

Completely stumped! Any help (preferably non-snarky) would be amaaaazing.

thanks!

Feather
  • 31
  • 4

2 Answers2

0

According to the documentation for Net::Twitter::Lite::WithAPIv1_1, the friend method returns a hashref:

  • friends
  • alias: friends_list
    • Parameters: user_id, screen_name, cursor
    • Required: none
    • Returns a cursored collection of user objects for users followed by the specified user.
    • Returns: HashRef

No where in there odes it say anything about JSON, so if you want to see the structure of the returned value, you can use Data::Dump or Data::Dumper

my $hashref = $nt->friends_list({ screen_name => 'someguyiknow' });

use Data::Dump;
dd $hashref;

If you have trouble navigating the returned structure, you could paste a copy of the dumped output here for advice. But nowhere should you need to use JSON.

Miller
  • 34,962
  • 4
  • 39
  • 60
0

References in perl are kinda like pointers in C, in that they're scalars, and you have to dereference them to use them as their referenced type, and the syntax is a bit funky. You probably want to read perldoc perlref for the full story.

First, according to the docs, friends_list returns a hashref, so you want to assign it to a scalar, not a list, so:

my $response = $nt->friends_list(blah);

Next, to use a hashref, you need to dereference it properly. Here's a simple example:

use warnings;
use strict;

my $hr = {# curly brackets make a hashref, see perldoc perldata
          one => 1,
          two => 2,
          three => 3,
          };

print $hr, "\n";
print %$hr, "\n";
print $$hr{one}, "\n";

foreach my $k (keys %$hr) {
  print "$k\n";
}

Which should output:

HASH(0x1fce1c)
three3one1two2
1
three
one
two

You can see the hashref being dereferenced as a hash with the %$hr, or to look up a key with $$hr{one}.

Chris

Chris Hecker
  • 93
  • 1
  • 6