Using JSON Datatypes in Macros: Difference between revisions

From RPTools Wiki
Jump to navigation Jump to search
mNo edit summary
m (Taustin moved page using JSON Datatypes in Macros to Using JSON Datatypes in Macros over redirect)
 
(2 intermediate revisions by 2 users not shown)
Line 9: Line 9:
* Attack penalty per shot (so more than one shot around has an attack penalty).
* Attack penalty per shot (so more than one shot around has an attack penalty).
So if we were to define this in JavaScript we could just do it as
So if we were to define this in JavaScript we could just do it as
<source lang="javascript" line>
<syntaxhighlight lang="javascript" line>
weapon = {
weapon = {
     "name": "Handgun",
     "name": "Handgun",
Line 15: Line 15:
     "damage": "1d10"
     "damage": "1d10"
}
}
</source>
</syntaxhighlight>


If you already know what your JSON object looks like defining it in MapTool is not too different.
If you already know what your JSON object looks like defining it in MapTool is not too different.
<source lang="mtmacro" line>
<syntaxhighlight lang="mtmacro" line>
[r: weapon = '{
[r: weapon = '{
     "name": "Handgun",
     "name": "Handgun",
Line 24: Line 24:
     "damage": "1d10"
     "damage": "1d10"
}']
}']
</source>
</syntaxhighlight>


If you copy and paste this into MapTool you will notice that the output is returned on one line  
If you copy and paste this into MapTool you will notice that the output is returned on one line  
<source lang="mtmacro" line>
<syntaxhighlight lang="mtmacro" line>
[r: weapon = '{ "name": "Handgun", "shots": 6, "damage": "1d10" }']
[r: weapon = '{ "name": "Handgun", "shots": 6, "damage": "1d10" }']
</source>
</syntaxhighlight>


This is because the chat window displays html and new line characters are not displayed. If you wanted to see the carriage returns as you typed them then you could do
This is because the chat window displays html and new line characters are not displayed. If you wanted to see the carriage returns as you typed them then you could do
<source lang="mtmacro" line>
<syntaxhighlight lang="mtmacro" line>
<pre>
<pre>
[r: weapon = '{
[r: weapon = '{
Line 40: Line 40:
}']
}']
</pre>
</pre>
</source>
</syntaxhighlight>
Which says the output is already preformatted so new line characters will be displayed.
Which says the output is already preformatted so new line characters will be displayed.


Line 46: Line 46:


So to create the above weapon you could use
So to create the above weapon you could use
<source lang="mtmacro" line>
<syntaxhighlight lang="mtmacro" line>
[r: weapon = json.set("{}", "name", "Handgun", "shots", 6, "damage", "1d10" )]
[r: weapon = json.set("{}", "name", "Handgun", "shots", 6, "damage", "1d10" )]
</source>
</syntaxhighlight>
Where {{code|"{}"}} is an empty JSON object, for convenience {{code|""}} can be used as the first argument to {{func|json.set}} to represent an empty object.
Where {{code|"{}"}} is an empty JSON object, for convenience {{code|""}} can be used as the first argument to {{func|json.set}} to represent an empty object.


{{func|json.set}} takes an object as well a list of key and value pairs and returns a new object with the specified keys set . '''It is important to rememeber this last bit, all of the json functions do not modify the object, instead they create a new object with the changes.'''
{{func|json.set}} takes an object as well a list of key and value pairs and returns a new object with the specified keys set . '''It is important to rememeber this last bit, all of the json functions do not modify the object, instead they create a new object with the changes.'''
For example
For example
<source lang="mtmacro" line>
<syntaxhighlight lang="mtmacro" line>
[h: weapon = json.set("{}", "name", "Handgun", "shots", 6, "damage", "1d10" )]
[h: weapon = json.set("{}", "name", "Handgun", "shots", 6, "damage", "1d10" )]
[h: weapon2 = json.set(weapon, "name", "Bigger Handgun")]
[h: weapon2 = json.set(weapon, "name", "Bigger Handgun")]
[r: weapon] <br>
[r: weapon] <br>
[r: weapon2]
[r: weapon2]
</source>
</syntaxhighlight>


Displays
Displays
Line 67: Line 67:
The original value in weapon has not been modified.  
The original value in weapon has not been modified.  


If you placed {{code|<source lang="text" enclose="none"><pre> </pre></source>}} around the output you will notice that json.set() creates the object on one line, not formatted nicely across multiple lines as it was when we created it manually. If you want to "format" this nicely you can use the {{func|json.indent}} command.
If you placed {{code|<syntaxhighlight lang="text" enclose="none"><pre> </pre></syntaxhighlight>}} around the output you will notice that json.set() creates the object on one line, not formatted nicely across multiple lines as it was when we created it manually. If you want to "format" this nicely you can use the {{func|json.indent}} command.


For example:
For example:
<source lang="mtmacro" line>
<syntaxhighlight lang="mtmacro" line>
<pre>[r: json.indent('{"name":"Handgun","shots":6,"damage":"1d10"}', 4)]</pre>
<pre>[r: json.indent('{"name":"Handgun","shots":6,"damage":"1d10"}', 4)]</pre>
</source>
</syntaxhighlight>


Produces:
Produces:
Line 85: Line 85:
Using JSON arrays is similar
Using JSON arrays is similar
Lets to our weapon above, in this mythical system that the gun belongs to you are able to fire all of the shots in one round but each after the first has a two hit penalty. We can represent this as an array with 6 elements (we will include the first shot for simplicities sake even if it would always be 0).
Lets to our weapon above, in this mythical system that the gun belongs to you are able to fire all of the shots in one round but each after the first has a two hit penalty. We can represent this as an array with 6 elements (we will include the first shot for simplicities sake even if it would always be 0).
<source lang="mtmacro" line>
<syntaxhighlight lang="mtmacro" line>
[r: modifiers = '[0, 1, 3, 5, 8, 12]']
[r: modifiers = '[0, 1, 3, 5, 8, 12]']
</source>
</syntaxhighlight>


The {{func|json.append}} function allows you to append items to the end of an array, if the array is empty then it will create a new one.
The {{func|json.append}} function allows you to append items to the end of an array, if the array is empty then it will create a new one.
Line 94: Line 94:


For example if I wanted to change the 3rd index in the array above to 4 I could do
For example if I wanted to change the 3rd index in the array above to 4 I could do
<source lang="mtmacro" line>
<syntaxhighlight lang="mtmacro" line>
[h: modifiers = json.set(modifiers, 2, 4)
[h: modifiers = json.set(modifiers, 2, 4)
</source>
</syntaxhighlight>
The value for index is {{code|2}} because indexes in the array start at {{code|0}}.
The value for index is {{code|2}} because indexes in the array start at {{code|0}}.


So given what we learned earlier you could add the modifiers to our weapon object in the following way
So given what we learned earlier you could add the modifiers to our weapon object in the following way
<source lang="mtmacro" line>
<syntaxhighlight lang="mtmacro" line>
[r: modifiers = '[0, 1, 3, 5, 8, 12]']
[r: modifiers = '[0, 1, 3, 5, 8, 12]']
[r: weapon = json.set(weapon, "modifiers", modifiers)]
[r: weapon = json.set(weapon, "modifiers", modifiers)]
</source>
</syntaxhighlight>


Or you could do it as
Or you could do it as
<source lang="mtmacro" line>
<syntaxhighlight lang="mtmacro" line>
[h: weapon = json.set("{}", "name", "Handgun", "shots", 6, "damage", "1d10",
[h: weapon = json.set("{}", "name", "Handgun", "shots", 6, "damage", "1d10",
     "modifiers", "[0, 1, 3, 5, 8, 12]" )]
     "modifiers", "[0, 1, 3, 5, 8, 12]" )]
<pre>[r: json.indent(weapon,4)]</pre>
<pre>[r: json.indent(weapon,4)]</pre>
</source>
</syntaxhighlight>


Which will display  
Which will display  
Line 131: Line 131:


Of course if you know all the details up front you can create the whole objects as before such as.
Of course if you know all the details up front you can create the whole objects as before such as.
<source lang="mtmacro" line>
<syntaxhighlight lang="mtmacro" line>
[r: weapon = '{
[r: weapon = '{
     "name" : "Handgun",
     "name" : "Handgun",
Line 138: Line 138:
     "modifiers" : "[0, 1, 3, 5, 8, 12]"
     "modifiers" : "[0, 1, 3, 5, 8, 12]"
}']
}']
</source>
</syntaxhighlight>




Line 146: Line 146:


So
So
<source lang="mtmacro" line>
<syntaxhighlight lang="mtmacro" line>
[h: weapon = json.set("{}", "name", "Handgun", "shots", 6, "damage", "1d10",
[h: weapon = json.set("{}", "name", "Handgun", "shots", 6, "damage", "1d10",
     "modifiers", "[0, 1, 3, 5, 8, 12]" )]
     "modifiers", "[0, 1, 3, 5, 8, 12]" )]
Line 154: Line 154:
[h: modifiers = json.get(weapon, "modifiers")]
[h: modifiers = json.get(weapon, "modifiers")]
Modifiers [r,c(json.get(weapon, "shots")): json.get(modifiers, roll.count)]
Modifiers [r,c(json.get(weapon, "shots")): json.get(modifiers, roll.count)]
</source>
</syntaxhighlight>




Line 167: Line 167:
You could also use {{func|json.length}} to change the line that displays the modifiers to
You could also use {{func|json.length}} to change the line that displays the modifiers to


<source lang="mtmacro" line>
<syntaxhighlight lang="mtmacro" line>
Modifiers [r,c(json.length(modfiers)): json.get(modifiers, roll.count)]
Modifiers [r,c(json.length(modfiers)): json.get(modifiers, roll.count)]
</source>
</syntaxhighlight>


But there is an easier way to loop through every value in the array and that is using [[foreach (roll option)|foreach]]
But there is an easier way to loop through every value in the array and that is using [[foreach (roll option)|foreach]]
<source lang="mtmacro" line>
<syntaxhighlight lang="mtmacro" line>
Modifiers [r,foreach(val,modifiers): val]
Modifiers [r,foreach(val,modifiers): val]
</source>
</syntaxhighlight>


json.length() and foreach can be used on JSON objects as well as arrays. In this case json.length() returns the number of key/value pairs, and foreach will loop through the keys in the object.
json.length() and foreach can be used on JSON objects as well as arrays. In this case json.length() returns the number of key/value pairs, and foreach will loop through the keys in the object.


So using the above objects
So using the above objects
<source lang="mtmacro" line>
<syntaxhighlight lang="mtmacro" line>
[r: json.length(weapon)]
[r: json.length(weapon)]
</source>
</syntaxhighlight>
Displays {{code|4}}.
Displays {{code|4}}.


and
and
<source lang="mtmacro" line>
<syntaxhighlight lang="mtmacro" line>
[r,foreach(val,weapon): val]
[r,foreach(val,weapon): val]
</source>
</syntaxhighlight>


Displays  
Displays  

Latest revision as of 20:45, 15 March 2023

If you don't know JavaScript or JSON already I highly suggest you read Introduction to JSON Datatypes first even though it is JavaScript based.

So how do you create JSON Objects and JSON Arrays in MapTool macro script? Well the easy way if you already know everything you want is to create it as a string. Lets define a data structure that will hold the details for a weapon.

The weapon will be a gun which has the following details:

  • Number of shots before reload
  • Damage done
  • Attack penalty per shot (so more than one shot around has an attack penalty).

So if we were to define this in JavaScript we could just do it as

weapon = {
    "name": "Handgun",
    "shots": 6,
    "damage": "1d10"
}

If you already know what your JSON object looks like defining it in MapTool is not too different.

[r: weapon = '{
    "name": "Handgun",
    "shots": 6,
    "damage": "1d10"
}']

If you copy and paste this into MapTool you will notice that the output is returned on one line

[r: weapon = '{ "name": "Handgun", "shots": 6, "damage": "1d10" }']

This is because the chat window displays html and new line characters are not displayed. If you wanted to see the carriage returns as you typed them then you could do

<pre>
[r: weapon = '{
    "name": "Handgun",
    "shots": 6,
    "damage": "1d10"
}']
</pre>

Which says the output is already preformatted so new line characters will be displayed.

The above is well and good if you know what you want to store ahead of time, but how do you create a JSON object based on user input or results of a macro. For this you use json.set().

So to create the above weapon you could use

[r: weapon = json.set("{}", "name", "Handgun", "shots", 6, "damage", "1d10" )]

Where "{}" is an empty JSON object, for convenience "" can be used as the first argument to json.set() to represent an empty object.

json.set() takes an object as well a list of key and value pairs and returns a new object with the specified keys set . It is important to rememeber this last bit, all of the json functions do not modify the object, instead they create a new object with the changes. For example

[h: weapon = json.set("{}", "name", "Handgun", "shots", 6, "damage", "1d10" )]
[h: weapon2 = json.set(weapon, "name", "Bigger Handgun")]
[r: weapon] <br>
[r: weapon2]

Displays

{"name":"Handgun","shots":6,"damage":"1d10"}
{"name":"Bigger Handgun","shots":6,"damage":"1d10"}

The original value in weapon has not been modified.

If you placed <pre> </pre> around the output you will notice that json.set() creates the object on one line, not formatted nicely across multiple lines as it was when we created it manually. If you want to "format" this nicely you can use the json.indent() command.

For example:

<pre>[r: json.indent('{"name":"Handgun","shots":6,"damage":"1d10"}', 4)]</pre>

Produces:

{
    "name": "Handgun",
    "shots": 6,
    "damage": "1d10"
}

Using JSON arrays is similar Lets to our weapon above, in this mythical system that the gun belongs to you are able to fire all of the shots in one round but each after the first has a two hit penalty. We can represent this as an array with 6 elements (we will include the first shot for simplicities sake even if it would always be 0).

[r: modifiers = '[0, 1, 3, 5, 8, 12]']

The json.append() function allows you to append items to the end of an array, if the array is empty then it will create a new one.

If the input is an "[]" it is an empty array, for convenience "" also represents an empty array. json.set() can be used on arrays but only to set a value for an index, the array must already have that index.

For example if I wanted to change the 3rd index in the array above to 4 I could do

[h: modifiers = json.set(modifiers, 2, 4)

The value for index is 2 because indexes in the array start at 0.

So given what we learned earlier you could add the modifiers to our weapon object in the following way

[r: modifiers = '[0, 1, 3, 5, 8, 12]']
[r: weapon = json.set(weapon, "modifiers", modifiers)]

Or you could do it as

[h: weapon = json.set("{}", "name", "Handgun", "shots", 6, "damage", "1d10",
    "modifiers", "[0, 1, 3, 5, 8, 12]" )]
<pre>[r: json.indent(weapon,4)]</pre>

Which will display

{
    "name": "Handgun",
    "shots": 6,
    "damage": "1d10",
    "modifiers":     [
        0,
        1,
        3,
        5,
        8,
        12
    ]
}


Of course if you know all the details up front you can create the whole objects as before such as.

[r: weapon = '{
    "name" : "Handgun",
    "shots" : 6,
    "damage" : 1d10,
    "modifiers" : "[0, 1, 3, 5, 8, 12]"
}']


The next question is now that we have all the information in a JSON object or array how do we get it out when we need it?

To get things out of objects or arrays we use json.get()

So

[h: weapon = json.set("{}", "name", "Handgun", "shots", 6, "damage", "1d10",
    "modifiers", "[0, 1, 3, 5, 8, 12]" )]
Weapon Name: [r: json.get(weapon, "name")]<br>
Damage: [r: json.get(weapon, "damage")] <br>
Shots: [r: json.get(weapon, "shots")] <br>
[h: modifiers = json.get(weapon, "modifiers")]
Modifiers [r,c(json.get(weapon, "shots")): json.get(modifiers, roll.count)]


Which displays

Weapon Name: Handgun 
Damage: 1d10 
Shots: 6 
Modifiers 0, 1, 3, 5, 8, 12

You could also use json.length() to change the line that displays the modifiers to

Modifiers [r,c(json.length(modfiers)): json.get(modifiers, roll.count)]

But there is an easier way to loop through every value in the array and that is using foreach

Modifiers [r,foreach(val,modifiers): val]

json.length() and foreach can be used on JSON objects as well as arrays. In this case json.length() returns the number of key/value pairs, and foreach will loop through the keys in the object.

So using the above objects

[r: json.length(weapon)]

Displays 4.

and

[r,foreach(val,weapon): val]

Displays

name, shots, damage, modifiers