Parsing JSON Data::Dumper output array in Perl - json

I'm trying to edit an old perl script and I'm a complete beginner. The request from the server returns as:
$VAR1 = [
{
'keywords' => [
'bare knuckle boxing',
'support group',
'dual identity',
'nihilism',
'support',
'rage and hate',
'insomnia',
'boxing',
'underground fighting'
],
}
];
How can I parse this JSON string to grab:
$keywords = "bare knuckle boxing,support group,dual identity,nihilism,support,rage and hate,insomnia,boxing,underground fighting"
Full perl code
#!/usr/bin/perl
use LWP::Simple; # From CPAN
use JSON qw( decode_json ); # From CPAN
use Data::Dumper; # Perl core module
use strict; # Good practice
use warnings; # Good practice
use WWW::TheMovieDB::Search;
use utf8::all;
use Encode;
use JSON::Parse 'json_to_perl';
use JSON::Any;
use JSON;
my $api = new WWW::TheMovieDB::Search('APIKEY');
my $img = $api->type('json');
$img = $api->Movie_imdbLookup('tt0137523');
my $decoded_json = decode_json( encode("utf8", $img) );
print Dumper $decoded_json;
Thanks.

Based on comments and on your recent edit, I would say that what you are asking is how to navigate a perl data structure, contained in the variable $decoded_json.
my $keywords = join ",", #{ $decoded_json->[0]{'keywords'} };

say qq{ #{ $arrayref->[0]->{'keywords'} } };
As TLP pointed out, all you've shown is a combination of perl arrays/hashes. But you should look at the JSON.pm documentation, if you have a JSON string.

The result you present is similar to json, but the Perl-variant of it. (ie => instead of : etc). I don't think you need to look into the json part of it, As you already got the data. You just need to use Perl to join the data into a text string.
Just to eleborate on the solution to vol7ron :
#get a reference to the list of keywords
my $keywords_list = $decoded_json->[0]{'keywords'};
#merge this list with commas
my $keywords = join(',', #$keywords_list );
print $keywords;

Related

Escape special characters in JSON string

I have Perl script which contains variable $env->{'arguments'}, this variable should contain a JSON object and I want to pass that JSON object as argument to my other external script and run it using backticks.
Value of $env->{'arguments'} before escaping:
$VAR1 = '{"text":"This is from module and backslash \\ should work too"}';
Value of $env->{'arguments'} after escaping:
$VAR1 = '"{\\"text\\":\\"This is from module and backslash \\ should work too\\"}"';
Code:
print Dumper($env->{'arguments'});
escapeCharacters(\$env->{'arguments'});
print Dumper($env->{'arguments'});
my $command = './script.pl '.$env->{'arguments'}.'';
my $output = `$command`;
Escape characters function:
sub escapeCharacters
{
#$env->{'arguments'} =~ s/\\/\\\\"/g;
$env->{'arguments'} =~ s/"/\\"/g;
$env->{'arguments'} = '"'.$env->{'arguments'}.'"';
}
I would like to ask you what is correct way and how to parse that JSON string into valid JSON string which I can use as argument for my script.
You're reinventing a wheel.
use String::ShellQuote qw( shell_quote );
my $cmd = shell_quote('./script.pl', $env->{arguments});
my $output = `$cmd`;
Alternatively, there's a number of IPC:: modules you could use instead of qx. For example,
use IPC::System::Simple qw( capturex );
my $output = capturex('./script.pl', $env->{arguments});
Because you have at least one argument, you could also use the following:
my $output = '';
open(my $pipe, '-|', './script.pl', $env->{arguments});
while (<$pipe>) {
$output .= $_;
}
close($pipe);
Note that current directory isn't necessarily the directory that contains the script that executing. If you want to executing script.pl that's in the same directory as the currently executing script, you want the following changes:
Add
use FindBin qw( $RealBin );
and replace
'./script.pl'
with
"$RealBin/script.pl"
Piping it to your second program rather than passing it as an argument seems like it would make more sense (and be a lot safer).
test1.pl
#!/usr/bin/perl
use strict;
use JSON;
use Data::Dumper;
undef $/;
my $data = decode_json(<>);
print Dumper($data);
test2.pl
#!/usr/bin/perl
use strict;
use IPC::Open2;
use JSON;
my %data = ('text' => "this has a \\backslash", 'nums' => [0,1,2]);
my $json = JSON->new->encode(\%data);
my ($chld_out, $chld_in);
print("Executing script\n");
my $pid = open2($chld_out, $chld_in, "./test1.pl");
print $chld_in "$json\n";
close($chld_in);
my $out = do {local $/; <$chld_out>};
waitpid $pid, 0;
print(qq~test1.pl output =($out)~);

How do I use encode_json with string in Perl?

Here is my code that I try to open the file to get data and change it to UTF-8, then read each line and store it in variable my $abstract_text and send it back in JSON structure.
my $fh;
if (!open($fh, '<:encoding(UTF-8)',$path))
{
returnApplicationError("Cannot read abstract file: $path ($!)\nERRORCODE|111|\n");
}
printJsonHeader;
my #lines = <$fh>;
my $abstract_text = '';
foreach my $line (#lines)
{
$abstract_text .= $line;
}
my $json = encode_json($abstract_text);
close $fh;
print $json;
By using that code, I get this error;
hash- or arrayref expected (not a simple scalar, use allow_nonref to allow this)
error message also point out that the problem is in this line;
my $json = encode_json($abstract_text);
I want to send the data back as a string (which is in UTF-8). Please help.
I assume you're using either JSON or JSON::XS.
Both allow for non-reference data, but not via the procedural encode_json routine.
You'll need to use the object-oriented approach:
use strict; # obligatory
use warnings; # obligatory
use JSON::XS;
my $encoder = JSON::XS->new();
$encoder->allow_nonref();
print $encoder->encode('Hello, world.');
# => "Hello, world."

Script extracts and prints UTF-8 words well, but prints JSON as garbage

I have tried my script on Mac OS Mavericks (perl 5.16.2) and Yosemite and also with Windows 7 (strawberry-perl-5.20.1.1-64bit-portable).
It is supposed to read UTF-8 data (russian text) and put it into a data structure - and finally print the data structure as JSON string (the output will be used to feed Core Data in an iOS word game).
The first part works (extracting words and printing them - to verify) works well, but the final part not: the resulting JSON string contains garbage:
Does anybody please know, how to fix my simple test script?
#!/usr/bin/perl -w
use strict;
use warnings;
use utf8;
use JSON;
binmode(STDOUT, ':utf8');
my $root = { words => [] };
while (<DATA>) {
chomp;
utf8::decode($_);
my #a = split /\s*[:,]\s*/;
my $words = [];
for my $word (#a[1 .. $#a]) {
print "WORD: $word\n";
#push #$words, utf8::encode($word);
push #$words, $word;
}
push #{$root->{words}}, $words;
}
print to_json($root, {utf8 => 1, pretty => 1});
__DATA__
Голова: небо, язык, мозг, глотка, надгортанник, пищевод, горло, гортань
Сумки: портмоне, кошелек, портфель, рюкзак, лямка, застежка
You're double encoding. You're encoding using from_json (utf8 => 1), then you're encoding again when outputting to STDOUT (binmode(STDOUT, ':utf8');).
The solution isn't clear, because it's not clear what you are trying to achieve. If you're really going to output non-JSON and JSON to STDOUT, don't ask from_json to encode.
The output looks "wrong", but that's OK: it's encoded. To see it correctly, just set
binmode STDOUT, ':raw';
before printing the JSON.
You can simplify the script by using encode_json:
#!/usr/bin/perl
use strict;
use warnings;
use utf8;
use JSON;
binmode(STDIN, ":utf8");
binmode(STDOUT, ":utf8");
my $root;
while (<DATA>) {
chomp;
my #words = split /\s*[:,]\s*/;
push #{ $root->{words} }, [];
for my $word (#words[1 .. $#words]) {
print "WORD: $word\n";
push #{ $root->{words}[-1] }, $word;
}
}
my $json = encode_json($root);
binmode STDOUT, ':raw';
print $json;

How to convert a simple hash to json in Perl?

I'm using the following code to encode a simple hash
use JSON;
my $name = "test";
my $type = "A";
my $data = "1.1.1.1";
my $ttl = 84600;
#rec_hash = ('name'=>$name, 'type'=>$type,'data'=>$data,'ttl'=>$ttl);
but I get the following error:
hash- or arrayref expected <not a simple scalar, use allow_nonref to allow this>
Your code seems to be missing some significant chunks, so let's add in the missing bits (I'll make some assumptions here) and fix things as we go.
Add missing boilerplate.
#!/usr/bin/perl
use strict;
use warnings;
use JSON;
my $name = "test";
my $type = "A";
my $data = "1.1.1.1";
my $ttl = 84600;
Make the hash a hash and not an array and don't forget to localise it: my %
my %rec_hash = ('name'=>$name, 'type'=>$type,'data'=>$data,'ttl'=>$ttl);
Actually use the encode_json method (passing it a hashref):
my $json = encode_json \%rec_hash;
Output the result:
print $json;
And that works as I would expect without errors.
Try %rec_hash = ... instead. # indicates a list/array, while % indicates a hash.

Print JSON object from Perl webservice

I am using Perl as my web-service.
I have my variables stored in pic1 and pic2 variables.
I want to make an JSON object from that and pass to the client side which is Sencha touch application(print that json object as done in "arch.twitter.com/search.json?q='test'") webservice.
I have done this much.
print header('application/json');
my %data = (img_one => $pic1,img_two => $pic2);
my $json_text = new JSON;
$json_text = to_json(\%data);
print $json_text;
Please guide me in this problem
You didn't specify what kind of modules are you using. CGI? CGI::Simple? Something different?
So I'll just give you very materialistic script to print simple JSON response.
#!/usr/bin/env perl
use strict;
use warnings;
use JSON;
my %data = (img_one => 'pic1', img_two => 'pic2');
print "Content-Type: application/json\n\n";
print to_json \%data;