How to check whether hash key contain JSON in perl? - json

I am sending a request to the endpoint url ,from there i am getting the response in case of success in form of JSON,but if it fails it return certain text .
Sending request:
$data->{response} = $self->{_http}->send($myData);
So before doing this:
$resp = from_json($data->{response});
i want to check whether the reponse is in json format or not .How we can handle this in Perl kindly help in this

You can catch exception thrown by from_json(),
my $resp;
my $ok = eval { $resp = from_json("{}"); 1 };
$ok or die "Not valid json";
or simpler,
my $resp = eval { from_json("rrr") };
$resp // die "Not valid json";

Use JSON or JSON::XS to decode the JSON into a Perl structure.
Simple example:
use strict;
use warnings;
use JSON::XS;
my $json = '[{"Year":"2012","Quarter":"Q3","DataType":"Other 3","Environment":"STEVE","Amount":125},{"Year":"2012","Quarter":"Q4","DataType":"Other 2","Environment":"MIKE","Amount":500}]';
my $arrayref = decode_json $json;
foreach my $item( #$arrayref ) {
# fields are in $item->{Year}, $item->{Quarter}, etc.
}

You could use a try/catch block using Try::Tiny
use Try::Tiny;
try {
$resp = from_json($data->{response});
} catch {
# Do something if it does not parse
warn 'Could not parse json'
};

Related

Perl HTTP Tiny response

How to put the JSON response of HTTP::Tiny in Perl?
use HTTP::Tiny;
my $response = HTTP::Tiny->new->get('http://example.com/');
die "Failed!\n" unless $response->{success};
print "$response->{status} $response->{reason}\n";
while (my ($k, $v) = each %{$response->{headers}}) {
for (ref $v eq 'ARRAY' ? #$v : $v) {
print "$k: $_\n";
}
}
print $response->{content} if length $response->{content};
How to put the $response->{content} into variable to be passed into html(tt2)?
You would pass your content to the TT processor like this:
use Template;
my $tt = Template->new;
$tt->process('some_template.tt', { content => $response->{content} })
or die $tt->error;
Perhaps you want to store it in an intermediate scalar first:
my $content = $response->{content};
$tt->process('some_template.tt', { content => $content })
or die $tt->error;
Perhaps you want to build up TT's variable hash before passing it to the processor.
my %vars;
$vars{content} = $response->{content};
$tt->process('some_template.tt', \%vars)
or die $tt->error;
Or you could use a hash reference instead of an actual hash:
my $vars;
$vars->{content} = $response->{content};
$tt->process('some_template.tt', $vars)
or die $tt->error;
Update: In a comment, simbabque suggests that you might actually be asking how to decode JSON content into an array or a hash. And I agree that's another way to interpret your question.
You'd need to use the JSON module. And it would look something like this:
use JSON;
my $json_parser = JSON->new; # Perhaps other options here, see docs.
my $decoded_json = $json_parser->decode($response->{content});

Parsing JSON In Perl

I'm trying to parse JSON data in Perl. it is request to Cisco Prime Service. My script works, but parsing doesn't work. And I have a warning,
malformed JSON string, neither array, object, number, string or atom, at character offset 0 (before "HTTP::Response=HASH(...") at InternetBSP.pl line 39.
It is here:
my $json_text = $json->allow_nonref->utf8->relaxed->escape_slash->loose->allow_singlequote->allow_barekey->decode($res);
have no Idee how should I fix it...
use strict;
use warnings;
use JSON -support_by_pp;
use LWP 5.64;
use LWP::UserAgent;
use MIME::Base64;
use REST::Client;
use IO::Socket::SSL;
#So dass es auch ohne SSL Sertifizierung funktioniert
BEGIN { $ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = 0 }
#Create a user agent object
my $ua = LWP::UserAgent->new(
ssl_opts => {
SSL_verify_mode => SSL_VERIFY_NONE(),
verify_hostname => 0,
}
);
#Create a request
my $req = HTTP::Request->new( GET => 'https://10.10.10.10/webacs/api/v1/data/AccessPoints.json?.full=true' );
$req->content_type('application/json');
$req->authorization_basic( "Username", "Password" );
#Pass request to the user agent and get a response back
my $res = $ua->request($req);
#Check the outcome of the Response
if ( $res->is_success ) {
print $res->content;
} else {
print $res->status_line, "n";
}
my $json = new JSON;
my $json_text = $json->allow_nonref->utf8->relaxed->escape_slash->loose->allow_singlequote->allow_barekey->decode($res);
#my try to pasre the data
foreach my $ap ( #{ $json_text->{queryResponse}->{'entity'} } ) {
print "------------------------\nAccess Point " . $ap->{'accessPointsDTO'}->{'#id'} . "\n";
print "Model:" . $ap->{'accessPointsDTO'}->{'model'} . "\n";
print "MAC Address:" . $ap->{'accessPointsDTO'}->{'macAddress'} . "\n";
print "Serial Number:" . $ap->{'accessPointsDTO'}->{'serialNumber'} . "\n";
print "Software Version:" . $ap->{'accessPointsDTO'}->{'softwareVersion'} . "\n";
print "Status:" . $ap->{'accessPointsDTO'}->{'status'} . "\n";
print "Location:" . $ap->{'accessPointsDTO'}->{'location'} . "\n";
}
I have this like outcome:
{"queryResponse":{"#last":"7","#first":"0","#count":"8","#type":"AccessPoints","#responseType":"listEntityInstances","#requestUrl":"https:\/\/10.66.1.23\/webacs\/api\/v1\/ data\/AccessPoints?.full=true","#rootUrl":"https:\/\/10.66.1.23\/webacs\/api\/v1\/data","entity":[{"#dtoType":"accessPointsDTO","#type":"AccessPoints","#url":"https:\/\/10 .66.1.23\/webacs\/api\/v1\/data\/AccessPoints\/205320"
But it shoud be smth like:
{"queryResponse":
{"#type":"AccessPoints",
"#rootUrl":"https://172.18.138.90/webacs/api/v1/data",
"#requestUrl":"https://172.18.138.90/webacs/api/v1/data/AccessPoints?.full=true",
"#responseType":"listEntityInstances",
"entity":[
{"#url":"https://172.18.138.90/webacs/api/v1/data/AccessPoints/13544533",
"#type":"AccessPoints",
"#dtoType":"accessPointsDTO",
"accessPointsDTO":
{"#id":"13544533",
"#displayName":"13544533",
"adminStatus":"ENABLE",
"bootVersion":"12.4.23.0",
"clientCount":0,
After update :)
------------------------
Access Point 205320
Model:AIR-LAP1142N-E-K9
MAC Address:6c:9c:ed:b5:45:60
Serial Number:FCZ1544W51B
Software Version:7.6.130.0
Status:CLEARED
Location:de.bw.stu.
------------------------
Access Point 205322
Model:AIR-CAP3502I-E-K9
MAC Address:0c:f5:a4:ee:70:10
Serial Number:FCZ184680VB
Software Version:7.6.130.0
Status:CLEARED
Location:de.bw.stu.
------------------------
Access Point 205324
Model:AIR-LAP1142N-E-K9
MAC Address:6c:9c:ed:86:9d:20
Serial Number:FCZ1544W50Y
Software Version:7.6.130.0
Status:CLEARED
Location:de.bw.stu.
malformed JSON string, neither array, object, number, string or atom, at character offset 0 (before "HTTP::Response=HASH(...")
This error message means that the data you are giving to decode is not JSON.
You are passing $res to decode, which is an HTTP::Response object (see above, emphasis mine). You need to use $res->content, which you use for debugging output a few lines above.
if ($res->is_success) {
print $res->content;
} else {print $res->status_line, "n";
}
I would rewrite that whole block of code to this.
die $res->status_line unless $res->is_success;
my $json = JSON->new->allow_nonref
->utf8->relaxed
->escape_slash->loose
->allow_singlequote->allow_barekey;
my $json_text = $json->decode( $res->content );
Instead of printing some debug output and then going on anyway if things went wrong you can just die if the request was not successful.
After that, create your JSON object and configure it. This is way more readable than this long line of code, and we're using a method call to new instead of indirect object notation.
Finally, we are decodeing $res->content.

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."

error handling for JSON data perl CGI Script

I am new to perl and I writing a simple cgi script in perl read Json data.. that looks like this
use CGI;
use JSON;
use strict;
my $cgi = CGI->new;
my $error=0;
$cgi->param();
my $data = $cgi->param('POSTDATA') || '{
"field1":"value1",
"field2":"value2"
}'; # Used a sample JSON with
my $json = JSON->new->utf8;
my $input = $json->decode ($data) || $error++;
my #errors=();
my %slots;
$slots{'coloumn1'} = $input->{'field1'} || $error++;
$slots{'coloumn2'} = $input->{'field2'} || $error++; # if there is no field2 in JSON it will increment value
if ( $error > 0) {
print $cgi->header('text/html','400 Bad Data');
print "error with $data ";
exit;
}
How can i do more sophisticated error handling for JSON to check if its a valid json string.....and raise exception if a field is missing in JSON string using eval or other methods??

How to post json data in a domain/url and displays the results in browser?

As a newbie in perl programming I still have troubles with it. I would like to ask how to post json data in a url and displays the results in a browser. I tried the script (below) and nothing happens; can't see data in the browser. I search for some codes to be tested but unluckily I didn't find any. I hope someone can advise me like if there is some codes I have to do. I'm pretty sure there is.
use warnings;
use strict;
use LWP::UserAgent;
use HTTP::Request::Common qw(POST);
my $ua = LWP::UserAgent->new;
my $server_endpoint = 'https://..';
my $req = HTTP::Request->new( POST => $server_endpoint );
$req->header( 'content-type' => 'application/json' );
my $data = '{
{"value1" : "THEI3435J",
"value2" : "3453fdf",
"value3" : "Sep452"
}
} ';
$request->content($data);
my $resp = $ua->request($request);
print $request->as_string;
if ( $resp->is_success ) {
my $message = $resp->decoded_content;
print "$message\n";
} else {
print "HTTP POST error code: ", $resp->code, "\n";
print "HTTP POST error message: ", $resp->message, "\n";
}
Your JSON is not valid as you have an extra pair of braces.
If you're unsure how to format the data, use the JSON module to do it for you:
use strict;
use warnings;
use JSON;
my %hash = (
value1 => "THEI3435J",
value2 => "3453fdf",
value3 => "Sep452",
);
print to_json( \%hash );
Outputs:
{"value1":"THEI3435J","value3":"Sep452","value2":"3453fdf"}