1

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.
6
  • 2
    You should really indent your code. It's very hard to read. Commented Feb 13, 2017 at 16:12
  • Thank you for advice! :) I'll try! Commented Feb 13, 2017 at 16:33
  • I formatted it for you using perltidy. Have a look at that tool, it's great! Commented Feb 13, 2017 at 16:56
  • @PerlDuck lots of Germans around today. StayCalm, you might want to drop by #perlde on irc.perl.org some time, the German Perl community is quite nice. Commented Feb 13, 2017 at 17:00
  • Thank you, @PerlDuck. I'll look throught Commented Feb 13, 2017 at 17:01

1 Answer 1

2

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.

Sign up to request clarification or add additional context in comments.

3 Comments

Bah, beat me to it. Might be worth adding mention how the error messages actually says this though :)
@Sobrique sorry about that. I'm lurking and waiting. :) Better?
Like that? #Pass request to the user agent and get a response back my $res = $ua->request($req); $res->content;

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.