Zum Ende der Metadaten springen
Zum Anfang der Metadaten

The class LoxBerry::JSON is intended to simplify working with json configuration files. It abstracts reading, writing and change recognition, and presents the content of the json file as a object variable. It supports simple key/value pairs, and also json objects and arrays. 

The advanced features allow to search for values in arrays and hashes.

LoxBerry Compatibility

This object class is in development. We will announce the version number, as soon as this feature is available.

Inclusions

This library automatically includes:

  • use JSON;

Abstract

use LoxBerry::JSON;
my $cfgfile = $lbpplugindir."/pluginconfig.json";

$jsonobj = LoxBerry::JSON->new();
$cfg = $jsonobj->open(filename => $cfgfile);

# Read values
print "Firstname: " . $cfg->{Firstname};
print "Sirname: " . $cfg->{Sirname};

# Change values
$cfg->{Firstname} = "Christian";
$cfg->{Sirname} = "Fenzl";

# Write 
$jsonobj->write();
# On every write, the class checks for changes and omits writing if nothing has changed

## Specials ##

# Enable debugging and dumping
$LoxBerry::JSON::DEBUG = 1; # Enables debug messages
$LoxBerry::JSON::DUMP = 1;  # Enables dumping of the current dataset

# Keep the file readonly in every case
$cfg = $jsonobj->open(filename => $cfgfile, readonly => 1);

# Write automatically on close
$cfg = $jsonobj->open(filename => $cfgfile, writeonclose => 1);

# Returns the filename
my $filename = $jsonobj->filename();

# Find
my @result = $jsonobj->find($cfg->{namesarray}, "$_->{Name} eq 'Christian'");
# See the detailed description for use-cases

# Dump
$jsonobj->dump{$cfg->{namesarray});

Parameter

ParameterOptionalDefaultDescription
filename

JSON file, that should be opened. If the file doesn't exist, it will be created on write.

writeonclose

x0

If 0, you need to explicitely call write. write can also be called multiple times.

If 1, the file is written automatically on descruction of the object.

readonlyx0If 1, every writing to the file is omitted.

Basically, the function always compares the initial content with the new content, and only writes, if the content has changed. This also happens when write is called explicitely.

With writeonclose => 1 is not written immediately on change of a value, but if the descructor is called, that means

  • on leaving the scope of the $jsonparser object (thereforce, define $jsonparser in the main section, if you want to use it globally)
  • on exit of the program.

Open and change JSON - Example

#!/usr/bin/perl
use LoxBerry::System;
use LoxBerry::JSON;

$LoxBerry::JSON::DEBUG = 1;
$LoxBerry::JSON::DUMP = 1;

my $jsonparser = Stats4Lox::JSON->new();
my $config = $jsonparser->open(filename => "/tmp/somefile.json", writeonclose => 0);

# Error handling
if (!$config) {
	print "Error loading file\n";
} else {
	print "File loaded\n";
}

print "Version of the file: $config->{Version}\n";

# Simple values
$config->{Info} = "Write data to JSON";
$config->{Version} = $config->{Version} + 1;

# Creating a json object MINISERVER_HASH with nested values	
$config->{MINISERVER_HASH}->{1}->{Name} = "MSOG";
$config->{MINISERVER_HASH}->{2}->{Name} = "MSUG";

# Creating an array 'Colors'
my @colors = ( "red", "blue", "green");
$config->{Colors} = \@colors;

# Creating a json object called 'Server' with some data
my %settings = ( "ip" => "192.168.0.1",
				 "port" => "8000",
				 "protocol" => "tcp"
				);
$config->{Server} = \%settings;
				
$jsonparser->write();

JSON Result

{
   "Colors" : [
      "red",
      "blue",
      "green"
   ],
   "Info" : "Write data to JSON",
   "MINISERVERS" : {
      "1" : {
         "Name" : "MSOG"
      },
      "2" : {
         "Name" : "MSUG"
      }
   },
   "Server" : {
      "ip" : "192.168.0.1",
      "port" : "8000",
      "protocol" : "tcp"
   },
   "Version" : 1
}

Search in JSON

The module implements a find function to search for elements in hashes and arrays.

my @result = $jsonparser->find(@/%element_to_search, $condition);

ParameterDescription
@/%element_to_search

The element_to_search must be an ARRAY (@something) or a HASH (%something).

Most likely you would send an object of the readed JSON, e.g. $config->{colors}

$condition

This must be a string that contains a valid Perl if condition, that is evaluated. \$_ is the current object in the condition.

Keep an eye on string interpolation:

  • Non-escaped sequences are interpolated BEFORE of the function evaluation
  • Escaped sequences are interpolated IN the funcation evaluation

Conditions must be able to be evaluated inside an if statement. Precisely it is evaluated as if ($perl_condition).

In the $condition, the $_ is the current evaluated object of the array/hash. Therefore, in your $condition you have to escape the element with \$_ .

In an ARRAY, \$_ therefore is the value of the array.

In an HASH, \$_ is the current evaluated object.

Both datatypes return an array with a list of the keys. In an ARRAY evaluation, the returning array holds the key number (0, 1, 2 etc). In an HASH evaluation, the returning array holds the key name of the found elements.

Double-check escaping in your condition!

my $house = "green";

my $condition_doublequotes = "\$_ eq \"$house\"";  → The function evaluates $_ eq "green" → OK

my $condition_doublequotes = "\$_ eq \$house"; → The function evaluates $_ eq $house. As $house is not defined in the function, it will raise an exception.

my $condition_singlequoutes = '$_ eq "' . $house . '"';  → The function evaluates $_ eq "green" → OK

my $condition_singlequoutes = '$_ eq "$house"';  → The function evaluates $_ eq "$house". As $house is not defined in the function, it will raise an exception.



See the examples.

#!/usr/bin/perl
use LoxBerry::System;
use LoxBerry::JSON;

## HASH search ##

# Creating a nested hash (1, 2 are names, not array elements)
$config->{MINISERVER_HASH}->{1}->{Name} = "MSOG";
$config->{MINISERVER_HASH}->{2}->{Name} = "MSUG";

# Search for a Miniserver named 'MSUG', returns an array with the hash keys
my @result = $jsonparser->find($config->{MINISERVER_HASH}, "\$_->{Name} eq 'MSUG'");
# Dump the result to STDERR
$jsonparser->dump(\@result, "Result of Hash search");

## ARRAY search ##


# Creating an array 'Colors'
my @colors = ( "red", "blue", "green");
$config->{Colors} = \@colors;


# Search for the colors 'red' or 'green', returns an array with the element indexes of the array
my @result = $jsonparser->find($config->{Colors}, "\$_ eq 'red' or \$_ eq 'green'");
# Dump the result to STDERR
$jsonparser->dump(\@result, "Result of Array search");

  • Keine Stichwörter