I have the following JSON content and I am trying to parse it by using perl (use JSON qw( decode_json );
here you have the complete JSON content,
{
"page": {
"currentPage": 1,
"totalPages": 1,
"pageSize": 45
},
"networkelements": [
{
"name": "aRestPM",
"alias": "",
"networkAddresses": [
{
"address": "135.244.37.111",
"port": 443,
"restResourceId": "135.244.37.111:443",
"connectionProtocol": "ADAPTER_MANAGED"
},
{
"address": "10.206.198.182",
"port": 443,
"restResourceId": "10.206.198.182:443",
"connectionProtocol": "ADAPTER_MANAGED"
}
],
"adapter": {
"name": "Simple RestService V1.0",
"version": "19.0.SR5a-STD-0.50_PM-SNAPSHOT"
},
"vendor": "Simple",
"model": "RestService",
"version": "V1.0",
"creationTime": "2022-04-07T20:32:22.368-0000",
"agentGroupName": "DefaultAgentGroup",
"connectivityState": "IN_CONTACT_CONDITIONAL",
"interfaces": [
{
"name": "REST",
"networkAddresses": [
{
"address": "135.244.37.111",
"port": 443
},
{
"address": "10.206.198.182",
"port": 443
}
],
"sessionCredentialAAAServer": "AAA",
"sessionCredential": {
"userId": "dummy"
},
"adminState": "ON_DEMAND",
"sessionAddresses": {},
"additionalAttributes": {}
}
],
"customAttributes": {},
"managementState": "MANAGED",
"emsServer": "No"
},
{
"name": "aRestPM_443",
"alias": "",
"networkAddresses": [
{
"address": "10.154.74.91",
"port": 443,
"restResourceId": "10.154.74.91:443",
"connectionProtocol": "ADAPTER_MANAGED"
}
],
"adapter": {
"name": "Simple RestService V1.0",
"version": "19.0.SR5a-STD-0.50_PM-SNAPSHOT"
},
"vendor": "Simple",
"model": "RestService",
"version": "V1.0",
"creationTime": "2022-05-16T13:06:01.928-0000",
"agentGroupName": "DefaultAgentGroup",
"connectivityState": "IN_CONTACT_CONDITIONAL",
"interfaces": [
{
"name": "REST",
"networkAddresses": [
{
"address": "10.154.74.91",
"port": 443
}
],
"sessionCredential": {
"userId": "dummy"
},
"adminState": "ON_DEMAND",
"sessionAddresses": {},
"additionalAttributes": {}
}
],
"customAttributes": {},
"managementState": "MANAGED",
"emsServer": "No"
}
]
}
I need to print name from networkelements array and address and ip from networkAddresses
the given json is in $keycloak_response
$decoded = decode_json($keycloak_response);
my @networkelements = @{ $decoded->{'networkelements'} };
my @net = @{ $decoded->{"networkelements"}[0]{"networkAddresses"} };
#print Dumper \@net;
foreach my $ne ( @networkelements ) {
$ne_name = $ne->{"name"};
$decoded2 = decode_json($ne);
my @net = @{ $decoded2->{"networkAddresses"} };
foreach my $ne ( @net) {
print $ne_name . "," . $ne->{"address"} . "," . $ne->{"port"} . "\n";
}
}
expected result is
aRestPM,135.244.37.111,443
aRestPM,10.206.198.182,443
aRestPM_443,10.154.74.91,443
I would really appreciate any advice.
Thanks
CodePudding user response:
decode_json( $ne )
is wrong since $ne
doesn't contain JSON.
for my $networkelement (@{ $decoded->{ networkelements } }) {
my $name = $networkelement->{ name };
for my $networkAddress (@{ $networkelement->{ networkAddresses } }) {
my $address = $networkAddress->{ address };
my $port = $networkAddress->{ port };
say join ",", $name, $address, $port;
}
}
You created needless copies of arrays, which I avoided. And I properly scoped my variables. Always use use strict; use warnings;
!
CodePudding user response:
JSON data should be decoded only once and you get fully restored structure of the data.
Reference: from_json
It does not require to create intermediary variables, you have full direct access to data of interest -- use it to your advantage.
Usage of map gives you access to elements of an array what allows to avoid loop.
use strict;
use warnings;
use feature 'say';
use JSON;
my $json = do { local $/; <DATA> };
my $data = from_json($json);
for my $e ( @{$data->{'networkelements'}} ) {
say join ',', $e->{name},$_->@{qw/address port/} for @{$e->{networkAddresses}};
}
exit 0;
__DATA__
{
"page": {
"currentPage": 1,
"totalPages": 1,
"pageSize": 45
},
"networkelements": [
{
"name": "aRestPM",
"alias": "",
"networkAddresses": [
{
"address": "135.244.37.111",
"port": 443,
"restResourceId": "135.244.37.111:443",
"connectionProtocol": "ADAPTER_MANAGED"
},
{
"address": "10.206.198.182",
"port": 443,
"restResourceId": "10.206.198.182:443",
"connectionProtocol": "ADAPTER_MANAGED"
}
],
"adapter": {
"name": "Simple RestService V1.0",
"version": "19.0.SR5a-STD-0.50_PM-SNAPSHOT"
},
"vendor": "Simple",
"model": "RestService",
"version": "V1.0",
"creationTime": "2022-04-07T20:32:22.368-0000",
"agentGroupName": "DefaultAgentGroup",
"connectivityState": "IN_CONTACT_CONDITIONAL",
"interfaces": [
{
"name": "REST",
"networkAddresses": [
{
"address": "135.244.37.111",
"port": 443
},
{
"address": "10.206.198.182",
"port": 443
}
],
"sessionCredentialAAAServer": "AAA",
"sessionCredential": {
"userId": "dummy"
},
"adminState": "ON_DEMAND",
"sessionAddresses": {},
"additionalAttributes": {}
}
],
"customAttributes": {},
"managementState": "MANAGED",
"emsServer": "No"
},
{
"name": "aRestPM_443",
"alias": "",
"networkAddresses": [
{
"address": "10.154.74.91",
"port": 443,
"restResourceId": "10.154.74.91:443",
"connectionProtocol": "ADAPTER_MANAGED"
}
],
"adapter": {
"name": "Simple RestService V1.0",
"version": "19.0.SR5a-STD-0.50_PM-SNAPSHOT"
},
"vendor": "Simple",
"model": "RestService",
"version": "V1.0",
"creationTime": "2022-05-16T13:06:01.928-0000",
"agentGroupName": "DefaultAgentGroup",
"connectivityState": "IN_CONTACT_CONDITIONAL",
"interfaces": [
{
"name": "REST",
"networkAddresses": [
{
"address": "10.154.74.91",
"port": 443
}
],
"sessionCredential": {
"userId": "dummy"
},
"adminState": "ON_DEMAND",
"sessionAddresses": {},
"additionalAttributes": {}
}
],
"customAttributes": {},
"managementState": "MANAGED",
"emsServer": "No"
}
]
}
Output
aRestPM,135.244.37.111,443
aRestPM,10.206.198.182,443
aRestPM_443,10.154.74.91,443
Note: printf can generate aligned output
printf "%-12s %-15s %d\n", $e->{name},$_->{address},$_->{port} for @{$e->{networkAddresses}};
Output
aRestPM 135.244.37.111 443
aRestPM 10.206.198.182 443
aRestPM_443 10.154.74.91 443