2017-02-13 4 views
1

Я пытаюсь разобрать данные JSON в Perl. это запрос к Cisco Prime Service. Мой скрипт работает, но разбор не работает. И у меня есть предупреждение,Parsing JSON In Perl

  malformed JSON string, neither array, object, number, string or atom, at character offset 0 (before "HTTP::Response=HASH(...") at InternetBSP.pl line 39. 

Именно здесь:

 my $json_text = $json->allow_nonref->utf8->relaxed->escape_slash->loose->allow_singlequote->allow_barekey->decode($res); 

нет навязчивой, как я должен это исправить ...

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"; 
} 

У меня это как результат:

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

Но это 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, 

После обновления :)

------------------------ 
    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. 
+2

Вы действительно должны отступать от своего кода. Это очень трудно читать. – simbabque

+0

Спасибо за совет! :) Я попробую! – StayCalm

+0

Я отформатировал его для вас, используя [perltidy] (http://perltidy.sourceforge.net/). Посмотрите на этот инструмент, это здорово! – PerlDuck

ответ

2

неверный формат JSON, строка, ни массив, объект, число, строка или атом, по характеру смещению 0 (перед "HTTP :: Response = HASH (... ")

Это сообщение об ошибке означает, что данные, которые вы передаете decode, не являются JSON.

Пройдено $res до decode, что является объектом HTTP::Response (см. Выше, основное внимание). Вам нужно использовать $res->content, который вы используете для отладки вывода на несколько строк выше.

if ($res->is_success) { 
    print $res->content; 
    } else {print $res->status_line, "n"; 
    } 

Я бы переписать, что весь блок кода для этого.

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); 

Вместо печати некоторый отладочный вывод, а затем происходит в любом случае, если все пошло не так, вы можете просто die, если запрос не был успешным.

После этого создайте объект JSON и настройте его. Это более читаемо, чем эта длинная строка кода, и мы используем вызов метода для new вместо обозначение косвенного объекта.

И наконец, мы находимся decode ing $res->content.

+0

Ба, избили меня до него. Может быть стоит добавить упоминание, как сообщения об ошибках на самом деле говорят об этом, хотя :) – Sobrique

+1

@ Собрике жаль об этом.Я прячусь и жду. :) Лучше? – simbabque

+0

Нравится? # Запросить запрос пользователю и получить ответ 'my $ res = $ ua-> request ($ req); $ res-> content; ' – StayCalm