user3587025
user3587025

Reputation: 183

Edit json using Perl

I need to edit the below config file using Perl. I need to check if cp is 10000 and set custcap to 99999 if so.

If the cp is not equal to 10000, just exit out of the file without making changes.

My understanding is we can use Perl file handles to open the file, and the JSON module for editing, but I'm not really sure about editing the file.

Can some one help me out with editing the file?

{
    "version": "15320029",
    "global": {
        "ap": {
            "log": "info",
            "hyd": {
                "log": "info",
                "qo": false
            }
        },
        "cus": [
            {
                **"cp": "10000"**,
                "ser": "XYZ",
                "usesr": false,
                "services": {
                    "acc": {
                        "ips": {
                            "usesr": false
                        }
                    }
                },
                "q": {
                    "policy": "CAP",
                    **"custcap": 3000000**
                }
            },
            {
            "cp": "10441",
                "ser": "abc",
                "usesr": false,
                "services": {
                    "acc": {
                        "ips": {
                            "usesr": false
                        }
                    }
                },
                "q": {
                    "policy": "CAP",
                    "custcap": 3000000
                }
            }
         ]  
      }

Code snippet :

#!/usr/bin/perl

use strict;
use warnings;
use JSON;

open my $fh, "<", "data.json";
my $json = <$fh>;
close $fh;


my $data = decode_json($json);

$data->{'q'}->{'custcap'}->[1] = "9999";

open my $fh, ">", "data.json";

print $fh encode_json($data);

close $fh;

Upvotes: 0

Views: 3118

Answers (3)

ikegami
ikegami

Reputation: 385829

Problem #1: You just read the first line of the file.

One trick to read the whole file at once is to use local $/. With some error checking and scoping, that will look like:

my $qfn = 'data.json';

my $json;
{
   open(my $fh, "<", $qfn)
      or die("Can't open file \"$qfn\": $!\n");
   local $/;
   $json = <$fh>;
}

Problem #2: You need some kind of loop since you need to check each of the objects in cus.

for my $cus (@{ $data->{global}{cus} }) {
   $cus->{q}{custcap} = 99999
      if $cus->{cp} == 10000;
}

Upvotes: 1

EmFi
EmFi

Reputation: 23450

@kjpires is correct that the posted snippet does not load the entire file, and will not parses it correctly.

That's only half the solution. The posted snippet traverses the JSON structure incorrectly.

The root node has a global node which has a cus node that is an array, and each cus node can have a q node which has a custcap property. Your snippet omits the cus array and attempts to access q directly

Your requirements aren't specific as to what to do if custcap appears multiple times. Assuming that you need to update each occurrence of custcap if its current value is 10000 with 99999 then you need to replace

$data->{'q'}->{'custcap'}->[1] = "9999";

with something like this:

for my $customer (@{$data->{global}{cus}}) {
      $customer->{q}{custcap} = 99999 if ($customer->{cp} == 10000);
}

Upvotes: 1

kjpires
kjpires

Reputation: 740

One problem is that my $json = <$fh>; doesn't read the whole file: you are just getting one line of the file (and then parsing just that one line which should probably fail unless it is all on one line).

One quick solution is to undefine the input end-of-line terminator using: $/ = undef; before you read your file. Another solution is to use the File::Slurp module.

Upvotes: 1

Related Questions