Home > OS >  Perl JSON arrays within a parent key
Perl JSON arrays within a parent key

Time:01-27

I have created a script to get some information from various external sources, the results should then be in json format. There is a lot of data and I push everything to an array in a loop, then print the json array after everything has been completed, an extract of that loop part of the script:

#!/usr/bin/perl
use JSON -convert_blessed_universally;
use strict;
use warnings;
my @json_arr;
my @servers = ("SERVER1", "SERVER2");
my @details = ("SERVER1,10.1.2.3,Suse Linux",
               "SERVER2,10.1.2.4,Windows 10",
               "SERVER3,10.1.2.5,Windows XP");
my $json = JSON->new->convert_blessed;

foreach my $server(@servers) {
    foreach (@details) {
        my @detail = split(',',$_);
        if ($server eq $detail[0]) {
          push @json_arr, {name => "$server", ip => "$detail[1]", os => "$detail[2]"};
      }
   }
}
my $result = $json->encode(\@json_arr);
print $result;

This gives an output of:

[
   {
      "name" : "SERVER1",
      "ip" : "10.1.2.3",
      "os" : "Suse Linux",
   },
   {
      "name" : "SERVER2",
      "ip" : "10.1.2.4",
      "os" : "Widows 10"
   }
]

and a screenshot:

enter image description here

I am however trying to do it by setting a key element instead and having the additional data as children of the device name, i.e:

[
  "instance" : [
       {
         "SERVER1" : {
                   "ip" : "10.1.2.3",
                   "os" : "Suse Linux"
       },
       "SERVER2" : {
                   "ip" : "10.1.2.4",
                   "os" : "Windows 10"
       }
    }
   ]
]

So I have tried a few things, including something like the below, then pushing to array, but I am getting funny results and just not getting the desired results.

my $json = '{
   "instance" : [
       $server => {
          ip => "$detail[0]",
          os => "$detail[1]"
       }
   ] 
}';
push @json_arr, $json;

CodePudding user response:

It only takes a small re-arrangement

use warnings;
use strict;
use feature 'say';

use Data::Dumper;
use JSON::XS;

...

my @json_ary;

foreach my $server (@servers) {
    foreach (@details) {
        my @detail = split /,/; 
        if ($server eq $detail[0]) {
            #push @json_ary, {name => "$server", ip => "$detail[1]" ...
            push @json_ary, 
                { $server => { ip => $detail[1], os => $detail[2] } } 
        }
    }   
}

print Dumper \@json_ary;

# Encode `{ instance => \@json_ary }` for the desired output
my $json = JSON->new->convert_blessed;
my $result = $json->encode( { instance => \@json_ary } );

say $result;

# One way to pretty-print a JSON string:
print JSON::XS->new->ascii->pretty->encode(decode_json $result);

A few notes

  • No need for quotes around variables, since they get evaluated anyway ("$detail[0]" --> $detail[0] etc)

  • No need for quotes around hash keys, as a syntax convenience: key => 'value' is OK (and if the value is a variable it's just key => $var). That is, as long as there are no spaces in the key name.

  • Related