How to Use JSON in Perl 6
1. Introduction
Perl 6 is the latest version of the Perl language—a long-time favorite scripting language of hackers and programmers everywhere. Perl itself is one of the first scripting languages in widespread use and has been used mainly in GNU/Linux systems by system administrators to automate tasks. Hackers prefer Perl because it’s easy to write one-off scripts. And with CPAN, you can find any module you need to get the job done.
Perl 6 has taken a long time to show up and only in Christmas 2015 did it get to a point where it can start to be widely used again. Perl 6 is ready to compete against Python and Ruby—the other dynamic scripting languages that have replaced Perl 5.
In this article, we’re going to do something very basic with Perl 6: reading and writing JSON files and objects. We will serialize and deserialize objects and hashes, into and out of, JSON objects.
We will lay out the code with a brief explanation and the code will be explained line by line. Links to further information about the Perl 6 language keywords or functions being used will also be included.
This tutorial is aimed at Perl 6 beginners.
Want to learn more about Perl? Get help from Perl experts
2. Installation and set up
There are two ways to install Perl 6: the easy way, and the slightly less easy way. We will also be installing the Perl 6 package manager, Panda.
If you’ve already set up Perl 6, you can find new modules and packages in the Perl 6 modules directory.
2.1. The Easy Way: RakudoBrew
Some of you may want to get up and running quickly with Perl 6. In that case, you can try using RakudoBrew. It is a shell script for GNU/Linux and Mac OS X which makes it easy to install Rakudo/MoarVM and Panda (Perl Package Manager).
2.1.1. RakudoBrew for GNU/Linux
Here is the command to run to use RakudoBrew on GNU/Linux:
git clone https://github.com/tadzik/rakudobrew ~/.rakudobrew
echo 'export PATH=~/.rakudobrew/bin:$PATH' >> ~/.bashrc
source ~/.bashrc
2.1.2 RakudoBrew for Mac OS X
Here is the command to run in the Terminal on Mac OS X to use RakudoBrew:
git clone https://github.com/tadzik/rakudobrew ~/.rakudobrew
echo 'export PATH=~/.rakudobrew/bin:$PATH' >> ~/.bash_profile
source ~/.bash_profile
2.1.3 Installing Rakudo and Panda
After RakudoBrew is installed you can use the following commands to install Perl 6 and Panda, the package manager:
rakudobrew build moar
rakudobrew build panda
2.2 The Slightly Less Easy Way
2.2.1 Installing Perl 6
The first step is to get Perl 6 installed. Since it isn’t widely used yet, you may have to go through some extra steps to get it installed on your operating system.
The primary (and popular) Perl 6 implementation is Rakudo Perl 6. You can follow the instructions here to install Rakudo.
On Fedora, I was able to install it like this:
dnf install rakudo
2.2.2 Installing Panda, Perl6 Package Manager
The instructions for install Panda are available here.
These are the commands:
git clone --recursive git://github.com/tadzik/panda.git
cd panda
perl6 bootstrap.pl
This, of course, requires that Perl6 is already installed.
2.3 Installing the JSON::Tiny package
With Perl 6 and its package manager installed, we can install the JSON library that we are going to use to read and write JSON objects. The library is called JSON::Tiny and while there are others, this particular library is very simple and easy to use which is perfect for us.
You can install the package with this command:
panda install JSON::Tiny
3. Loading a JSON object from a string
Let’s jump right in and look at some code. We are going to be creating a JSON object within a string, parsing that JSON string and turning it into a hash.
Create a new file named load-json-from-string.pl6
and type in the following source code:
use JSON::Tiny;
my $json_as_string = '{"carType":"BMW", "quantity":3, "price":"32000.00"}';
my %json = from-json $json_as_string;
my $description = q:to/END/;
The car type is %s.
There are %d cars available.
The price is $%.2f.
END
say $description.sprintf(%json<carType>, %json<quantity>, %json<price>);
You will see that in the first line we are importing the JSON::Tiny package with the use keyword.
In the next line, we are storing a JSON object as a string. The my keyword is used to declare a local variable. The JSON object has three fields, carType, quantity, and price. The carType and price are strings, and the quantity is an integer. When we parse that JSON object into a hash, we expect that the types of the fields are preserved.
After we imported the JSON::Tiny library, we gained access to two functions: to-json
and from-json
. In this case, we’re interested in loading a JSON object from a string so we use the from-json
function to convert the string. You can see how to do this in line 3.
What’s stored in %json
is a hash table (also known as a dictionary or map). There are three keys in this hash table that match the JSON fields, “carType”, “quantity”, and “price”.
Next, we define the description of the object we will be printing out. We use a heredoc which will be familiar to those programmers who have used Perl before. A heredoc is a way to define a multi-line string. If you’re a Perl user, you will notice that the syntax to start a heredoc has changed.
In the description, we use a few special formatting options to indicate where the type of data we will be printing. The formatting options are used by the sprintf
function. In line 9 we will be printing out the result of using sprintf
to supply values to the format string description
.
Let’s run the program:
perl6 load-json-from-string.pl
We will get the following output:
The car type is BMW.
There are 3 cars available.
The price is $32000.00.
So that’s how we parse a JSON object from a string into a hash table and access and display the keys and values in that hash table.
4. Creating a JSON object from a hash table
Now we are going to create a hash table and then turn it into a JSON object.
Create a new file named hash-into-json.pl6
.
Here is how it will look (explanation for the code is below):
use JSON::Tiny;
my %dealership = cars => ['Ford', 'BMW'], avgTestDrivesPerWeek => 15.1;
my $json_as_string = to-json %dealership;
say $json_as_string;
say 'Is it a string? ' ~ ($json_as_string ~~ Str);
As before, we import the JSON::Tiny module.
Then we create the hash table. The types of data stored are basic data types like strings and numbers and arrays. In our example, we’re storing a list of strings naming the cars that are in the car dealership, and we’re also storing the average number of test drives per week.
Next, we use the handy to-json
function provided by JSON::Tiny to convert the hash table into a JSON object. We store the result in $json_as_string
.
Finally, we display the JSON object string.
In the last line, we are using the string concatenation operator, ~
, to create the sentence and printing out true or false depending on if the $json_as_string
variable is of the string type.
Now let’s run the program:
perl6 hash-into-json.pl6
You should see this result:
{ "avgTestDrivesPerWeek" : 15.1, "cars" : [ "Ford", "BMW" ] }
Is it a string? True
5. Creating a JSON object from a class object
In the previous example, we converted a simple hash table into a JSON object. Things become more interesting when we want to convert other types of objects into JSON objects.
To do this, we need to define a new method that matches the type of the class and has the same name as the to-json
function. This is known as multiple dispatch where the method that is called is based on the arguments supplied to that function.
In JSON::Tiny, when the to-json
method is called with a boolean value, it will check the value and print out either “true” or “false”. The method called will be the one where the argument is of the Bool
type.
JSON::Tiny defines a few other methods for other types of arguments:
• Real (numbers)
• Str (string)
• Bool (boolean)
• Associative (maps, hash tables)
• Positional (lists, arrays)
So we have to do the same thing and define our own to-json
method that is dispatched when the argument given to it matches our class.
Before we do anything we have to import the JSON::Tiny package:
use JSON::Tiny;
Let’s create our class. It is an art gallery class that stores the name of the gallery, the year it was established and an array of paintings it has sold:
class ArtGallery {
has Str $.name is required;
has Int $.yearEstablished;
has Str @.paintings-sold;
}
Now let’s use multiple dispatch and define the to-json
method that accepts a defined instance of the ArtGallery
class:
multi to-json(ArtGallery:D $d) {
my %h =
name => $d.name,
year_established => $d.yearEstablished,
paintings_sold => $d.paintings-sold;
to-json %h;
}
Next, let’s define an instance of the ArtGallery
class. It will be named Cool Art Gallery
, it was established in the year 1812 and it has sold three paintings. Of special note here is that the list of paintings sold is separated by semi-colons rather than commas (see the Perl 6 List Literals documentation for more information about list creation syntax).
my $art_gallery = ArtGallery.new(
:name('Cool Art Gallery'),
:yearEstablished(1812),
:paintings-sold('Woman with a parasol'; 'Beach in Pourville'; 'The Magpie')
);
Then, print it out as a JSON object string:
say to-json($art_gallery);
Run the program:
perl6 object-to-json.pl6
The output of running this program is this:
{ "name" : "Cool Art Gallery", "year_established" : 1812, "paintings_sold" : [ "Woman with a parasol", "Beach in Pourville", "The Magpie" ] }
The source code for the whole program looks like this:
# object-to-json.pl6
use JSON::Tiny;
class ArtGallery {
has Str $.name is required;
has Int $.yearEstablished;
has Str @.paintings-sold;
}
multi to-json(ArtGallery:D $d) {
my %h =
name => $d.name,
year_established => $d.yearEstablished,
paintings_sold => $d.paintings-sold;
to-json %h;
}
my $art_gallery = ArtGallery.new(
:name('Cool Art Gallery'),
:yearEstablished(1812),
:paintings-sold('Woman with a parasol'; 'Beach in Pourville'; 'The Magpie')
);
say to-json($art_gallery);
6. Saving a JSON object to a file
In the next example, we are going to save the class as a JSON object into a file. We’re going to re-use the previous code for the ArtGallery class definition, the to-json
definition and create an instance of an ArtGallery.
The new part that we’re adding is writing (also known as saving) the JSON object string to a file.
my $fh = open 'art_gallery.json', :w;
$fh.say(to-json($art_gallery));
$fh.close;
The shorter way of saving a string to a file is:
spurt 'art_gallery.json', to-json($art_gallery);
The Perl 6 Documentation on Writing Files is very informative and provides more examples of doing this.
The source code for the whole program looks like this:
# object-to-json-file.pl6
use JSON::Tiny;
class ArtGallery {
has Str $.name is required;
has Int $.yearEstablished;
has Str @.paintings-sold;
}
multi to-json(ArtGallery:D $d) {
my %h =
name => $d.name,
year_established => $d.yearEstablished,
paintings_sold => $d.paintings-sold;
to-json %h;
}
my $art_gallery = ArtGallery.new(
:name('Cool Art Gallery'),
:yearEstablished(1812),
:paintings-sold('Woman with a parasol'; 'Beach in Pourville'; 'The Magpie')
);
my $fh = open 'art_gallery.json', :w;
$fh.say(to-json($art_gallery));
$fh.close;
When we run the code, it will create an ArtGallery object, convert it to JSON and save it to art_gallery.json
.
Run the code like this:
perl6 object-to-json-file.pl6
You can check if it worked by opening the file art_gallery.json
. It should look like this:
{ "name" : "Cool Art Gallery", "year_established" : 1812, "paintings_sold" : [ "Woman with a parasol", "Beach in Pourville", "The Magpie" ] }
Wrapping up
In this tutorial, we’re introduced to Perl 6 by reading and writing JSON files and objects. Hopefully, this will pick up your interest with Perl and continue learning more about it.
Other related tutorials and tips
- Use LWP::JSON::Tiny for JSON web APIs in Perl
- How to Convert JSON to Markdown using json2md
- Is there any way to import a json file(contains 100 documents) in elasticsearch server.?