JSON

Chapter External APIs describes how to start working with JSON. Now it's about time to saddle up 🐎, guys!

There might be a need to place a few variables in the same record. Just like a tiny ladies purse that is eventually able to store a great number of things inside.

OK, let's talk about Mary Jane. She is just a girl who felt really bored on August 7, 2018. And at 10:36 p.m. that day she decided to message this guy she liked, whose name was JSON, saying that she had a crush on him.

Time must be converted to UNIX format. This format is suitable for calculations and allows, for example, to deduct one date from another. Convert time to UNIX and backwards here. Using UNIX we converted August 7, 2018, 10:36 p.m. to 1533670582.

Next we should add all of the given parameters to %X variable as a JSON record:

%X={"Name":"Mary Jane","Message":"I ❤️ JSON","Time":1533670582}

So, our variable X contains such parameters:

Name="Mary Jane"

Message="I ❤️ JSON"

Time=1533675776

This is the view of the formatted JSON record:

{
"Name": "Mary Jane",
"Message": "I ❤️ JSON",
"Time": 1533670582
}

🐫 Watch out: always enclose words in quotation marks, but leave numbers as is.

Well, sounds good. Now it’s time to teach your bot the same thing.

JSON node contains the following parameters:

$.jsonPath %variable method(),

where jsonPath — path to the variable inside of JSON (not required for working with a root entry)

%variable — variable that contains JSON record;

method() — method name (not used for read-only mode).

Reading variables from JSON

As you probably remember X variable contains JSON record {"Name":"Mary Jane","Message":"I ❤️ JSON","Time":1533670582} or:

{
"Name": "Mary Jane",
"Message": "I ❤️ JSON",
"Time": 1533670582
}

How to separate Message body from our JSON record:

%Y=$.Message %X

Now %Y variable contains text “I ❤️ JSON”.

Cheers!

All right, time to go for something more complicated. So, this time we are asking our Mary Jane (and she is 31 btw) to go grocery shopping. As a decent housewife she prepared the grocery list and even classified all stuff she needs to fruits, vegetables and meat groups.

{
"name": "Mary Jane",
"age": 31,
"gender": "Female",
"grocery": [
{
"name": "Fruits",
"variety": [
"Orange",
"Apple",
"Strawberry"
]
},
{
"name": "Vegetables",
"variety": [
"Avocado",
"Tomato",
"Chilli"
]
},
{
"name": "Meat",
"variety": [
"Pork",
"Beef",
"Chicken"
]
}
]
}

How to figure out what the first item in the meat group from Mary Jane`s list is? To do so we need to specify a correct path to the sought variable in JSON record. This would be the correct path: grocery[2].variety[0]

And that's the node with %Y variable, that is going to contain the result we need:

%Y=$.grocery[2].variety[0] %X

So, how do we get the correct result? In the example above JSON record has variables on a few levels. The first level includes name, age, gender and grocery. We need grocery, since it contains the list of products. Meat group is the third in the row, but it is numbered as 2, because JSON numbering starts at 0, not at 1. That's why grocery[2] is supposed to mean that we got to the right group - MEAT. Now all is left is to choose the first item and its number is 0. This is how we get variety[0]. That means grocery[2].variety[0] defines the path with the correct answer and %Y=$JSON %X grocery[2].variety[0] ends up with %Y variable containing Pork.

Whew, that's it!

🐫 Go to http://jsonpath.com and check if the path to JSON variable is correct.

But what if we have no clue where exactly meat products are on the list? Then we are going to search by name:

%Y=$.grocery[?(@.name=="Meat")].variety[0] %X

We specified the name of the group as Meat and selected the first item. Here we go — it's Pork 🐷!

Moreover, if needed, it is possible to get a batch of data from JSON. Here is how we get all meat items from famous Mary Jane’s list:

%Y=$.grocery[?(@.name=="Meat")]

As a result %Y variable turns to JSON record containing this:

{
"name": "Meat",
"variety": [
"Pork",
"Beef",
"Chicken"
]
}

Expanding of JSON data

How to add new details to JSON? As you may remember our JSON is still there: %X. Imagine, Mary Jane forgot to put some cheese on the list. Let’s fix it by creating %Z variable containing a few kinds of cheese:

%Z={"name":"Cheese","variety":["Cheddar","Mozzarella","Feta"]}

Then we should add that to %X variable:

$JSON %X grocery add(%Z)

Voila! Welcome expanded JSON:

{
"name": "Mary Jane",
"age": 31,
"gender": "Female",
"grocery": [
{
"name": "Fruits",
"variety": [
"Orange",
"Apple",
"Strawberry"
]
},
{
"name": "Vegetables",
"variety": [
"Avocado",
"Tomato",
"Chilli"
]
},
{
"name": "Meat",
"variety": [
"Pork",
"Beef",
"Chicken"
]
},
{
"name": "Cheese",
"variety": [
"Cheddar",
"Mozzarella",
"Feta"
]
}
]
}

Removal by field value

Time to get rid from the meat in our list:

$.grocery %X remove({"name":"Meat"})

You can also delete data by using

$.grocery[?(@.name=="Meat")] %X remove()

Just like that we transformed Mary Jane to a vegetarian.

Extraction of the last JSON item

Let it be the recently added cheese item:

%Y=$.grocery[?(@.name=="Cheese")].variety %X pop()

%Y will end up having Feta. Same time this item is going to be removed from JSON record.

Iteration

Okay, this is the really exciting part.

JSON contains batches of similar items such as a fruit list. To get all of the items from the fruit list type the following:

$.grocery[?(@.name=="Fruits")].variety %X each(%item)

We had JSON %X, added the path to fruits $.grocery[?(@.name=="Fruits")].variety and put each fruit to %item.

Then we need to divide the node into two branches:

  1. @next — further action with %item. In our example its meaning appears in a message.
  2. @exit — if there are no more items, the bot will go further as per the map flow.

Very well!

See both examples on the map:

Click icon to copy this map or open it in