[MapTool] JSON Tutorials

Doc requests, organization, and submissions

Moderators: dorpond, trevor, Azhrei

Nonsapient
Cave Troll
Posts: 90
Joined: Thu Apr 23, 2009 6:37 pm

[MapTool] JSON Tutorials

Post by Nonsapient »

Okay guys, I am befuddled by JSON items. I shirk from them much like I would a Cthulhian horror.

Can anyone direct me to a comprehensive tutorial for JSON that pertains to maptool? I know many of the things I need/want are far easier to do with JSON.
There is this, but I honestly freeze up a bit when I see it.

Any help would be appreciated.

User avatar
biodude
Dragon
Posts: 444
Joined: Sun Jun 15, 2008 2:40 pm
Location: Montréal, QC

Re: [MapTool] JSON Tutorials

Post by biodude »

Hmm. If the tutorial is overwhelming, that's unfortunate :(

I was a little intimidated until I found this concise description of json objects and arrays. There's a lot of technical programming notation there, but once I got the basic jist of things, it made a lot more sense.

Without a specific question, all I can offer for the moment is the following:

If you are familiar with Lists and String Property lists (Wiki: getStrProp(), for example), there are analogous data structures in json form. The main difference is that json structures use more complex delimeters and structures, making them much more flexible in terms of their contents. Don't worry about the actual formatting: the json functions will take care of this for you.
I find it easier to not even think about the format of json entities: just think in terms of the structure and stick to the json-specific functions and you'll be fine.

json arrays are like lists, but fancier. Kind of like arrays in most programming languages (but they primarily hold strings or numbers). In fact, there are many more things you can do with a json array than with a list (Wiki: json.unique(), Wiki: json.intersection(), etc.)

json objects are like String Property Lists ( name = value ; ), but fancier and more flexible. Because both names (keys) and values can be entire strings, you can include "reserved" characters (like = or ; or spaces or whatever) with impunity, and it won't break the structure. (It is still probably a good idea to use Wiki: encode() on any strings hat get stored in a json object, especially if it's entered by a user input or somesuch).


It might help to find some example and play with them. Here's a few from my learning process:
ExampleJSONcode

Code: Select all

<!-- json functions -->
[H: json.object1 = json.set("", 'first', 1, 'second', 2, 'third', 3)]
[H: json.object2 = json.set("", 'first', 2, 'second', 4, 'fourth', 6)]
[json.union(json.object1, json.object2)]    <!-- array of all field names in either object -->
[json.intersection(json.object1, json.object2)]    <!-- array of all field names in BOTH object -->
[json.merge(json.object1, json.object2)]    <!-- object with keys from both objects -->
[R: json.evaluate(json.object1)]

<!-- sum of JSON object values -->
[R: json.object1 = json.set("", 0, 1, 1, 2, 2, 3)]
[R: json.get(json.object1, "first")]
[R: valueList = ""]
[R, C(json.length(json.object1), ";"): valueList = listAppend(valueList, string(json.get(json.object1,roll.count)) )]
[R: valueArray = json.fromList(valueList)]
[sum(json.toList(valueArray))]    <!-- still only creates a string list -->
[eval( "sum("+ valueList +")" )]    <!-- the eval wrapper is needed because the math functions dont work on STRING lists ( each item must be a separate argument )-->

<!--    building dynamic input parameter from a string    -->
[ inputLine = "%s | %s | %s | %s | %s" ]
[ inputParam = strformat( inputLine, "varName", defaultValue, promptLabel, inputType, parameters )]    <!-- if optional parameters are not used, a blank string ("") must still be specified as an argument for strformat() to work -->
[ input( inputParam )]
<!-- e.g. -->
[H: inputLine = "%s | %s | %s | %s | %s" ]
[H: inputArg = strformat( inputLine, "varName", "defaultValue", "promptLabel", "TEXT", "" )]    <!-- if optional parameters are not used, a blank string ("") must still be specified as an argument for strformat() to work -->
[H: input( inputArg, "", inputArg )]    <!-- input still works with empty arguments -->
[R: varName ]
[H: inputParameters = json.append( "", inputArg, inputArg )]
[H: inputParameters = json.toList( inputParameters, "##" )]
[H: input( inputParameters )]    <!-- input still works with empty arguments, but NOT if separated by "##"  -->
<br>[R: varName ]

<!-- building dynamic inputs from a string list!
Thanks again, zEal
http://forums.rptools.net/viewtopic.php?f=20&t=10114&start=0 -->
<!-- use json.merge() to insert a previously built section somewhere in the middle -->
[ InputParameters = json.append( "",
    "tab|Tab|Tab|TAB",
    "text|Default Text|Text|TEXT",
    "list|List Item 1, List Item 2|List|LIST",
    "check|1|Check Box|CHECK",
    "radio|Radio1, Radio2|Radio|RADIO",
    "label|Label|Label|LABEL",
    "props|Prop1=1;Prop2=2|Props|PROPS"
)]
[ InputParameters = json.toList( InputParameters, "##" )]
[ input( InputParameters )]

 
"The trouble with communicating is believing you have achieved it"
[ d20 StatBlock Importer ] [ Batch Edit Macros ] [ Canned Speech UI ] [ Lib: Math ]

User avatar
aliasmask
RPTools Team
Posts: 9023
Joined: Tue Nov 10, 2009 6:11 pm
Location: Bay Area

Re: [MapTool] JSON Tutorials

Post by aliasmask »

I feel your pain. I was up late last night trying to figure these things out too when I stopped to realize that "class" is a javascript reserved word and doesn't work. It's in the notes of the wiki under json.set, but was more focused on json.get and didn't see it until much later.

Here's how I understand the structure so far.

You have 2 things, arrays and objects. Arrays are simple enough to comprehend. They are surrounded by brackets "[ ]" and separated by commas ",".

Examples:
[1,2,3]
["bob","joe","jane"]
[1,"joe",3]

What's between the commas doesn't matter as long as it's a valid datatype (string, number, array or object). So, you can have:

["bob",2,[1,2,3],{"varName":"value"}]

The problem I found to get to this point without using json.set or json.append is that I can't type [h: myArray = ["bob",2,[1,2,3],{"varName":"value"}]] because you'll get "unexpected char: '{'". But it will work if you surround it with a "squote" (single quote, or superquote) like so, [h: myArray = '["bob",2,[1,2,3],{"varName":"value"}]'].

But if you're building a data structure from scratch, you may want to consider using json.set or json.append for arrays.

Example:

Code: Select all

[h: obj = json.set("{}","varName","badvalue")] <!-- create object -->
[h: arr = json.append("",1,2,4)] <!-- create array -->
[h: arr = json.set(arr,2,3)] <!-- fix value is position 2, to value 3 -->
[h: arrStruct = json.append("","bob",2,arr,obj)] <!-- create new array with append -->

[r: arrStruct]<br> <!-- what we have so far -->

<!-- the complicated way to set nested objects and arrays (set(set(get)))-->
[h: arrStruct = json.set(arrStruct,3,json.set(json.get(ArrStruct,3),"varName","goodvalue"))]
[r: arrStruct]<br>

<!-- the easy way (get,set,set) -->
[h: pos3 = json.get(arrStruct,3)] <!-- get object from array position 3 -->
[h: pos3 = json.set(pos3,"varName","another value")] <!-- set object to new value -->
[h: arrStruct = json.set(arrStruct,3,pos3)] <!-- put object back in array position 3 -->
[r: arrStruct]<br>

<!-- This doesnt work -->
[h: newArr = json.set("",1,2,3,4)]
[r: newArr]<br>

<!-- But this does -->
[h: newArr = json.append("",1,2,3,4)]
[r: newArr]<br>
 
As far as I can tell, you can't use json.set to set array positions that don't exist. I hope this gets you started on understanding. I know it was a learning experience for me just to write this post :)

User avatar
Rumble
Deity
Posts: 6235
Joined: Tue Jul 01, 2008 7:48 pm

Re: [MapTool] JSON Tutorials

Post by Rumble »

Unless you're making a trivial object or array - something like

Code: Select all

'{"Yay":5, "Nay":2}'
I would do all assembly of JSON datatypes using the functions. It's just easier.

Nonsapient
Cave Troll
Posts: 90
Joined: Thu Apr 23, 2009 6:37 pm

Re: [MapTool] JSON Tutorials

Post by Nonsapient »

I appreciate ya'll's help. I haven't had a chance to do any coding yet, but when I do I'm sure I'll be asking questions.

User avatar
Irrlicht
Dragon
Posts: 426
Joined: Mon Feb 09, 2009 10:53 am

Re: [MapTool] JSON Tutorials

Post by Irrlicht »

I have a few questions:
1) Does using json to store "large" numbers of properties reduce the memory usage?
2)Since I've been after these darn json for days and coundn't understand a thing about how to use them as I need (I can't even use json.get from a campaign property as I'd wish, despite trying and trying), could someone please tell me which pages (wiki or not) should I read in order to finally understand how the hell does it work?
"There are many ways my Son, to find where the souls of Demons remain...
But it takes only one second of despair and of doubt until, at last, your Soul they will gain..."

User avatar
Rumble
Deity
Posts: 6235
Joined: Tue Jul 01, 2008 7:48 pm

Re: [MapTool] JSON Tutorials

Post by Rumble »

Irrlicht wrote:I have a few questions:
1) Does using json to store "large" numbers of properties reduce the memory usage?
2)Since I've been after these darn json for days and coundn't understand a thing about how to use them as I need (I can't even use json.get from a campaign property as I'd wish, despite trying and trying), could someone please tell me which pages (wiki or not) should I read in order to finally understand how the hell does it work?

Not sure I can address the first question, but the second question I can address.

The wiki tutorial on JSONs is not maptool specific - it's about the idea of the JSON format. For maptool purposes, though, look at it this way:

JSON Objects and JSON Arrays are two variable types that MapTool macros can manipulate. In MapTool, they are formatted in a particular way (enclosed in { } or [ ], respectively) and it is that formatting that clues MapTool in to the type of variable you're talking about.

In essence, they are a simple way to store data of various kinds in a single variable, and then retrieve it (in this manner, they are quite similar to String Lists and String Property Lists, which you might already be familiar with). There are important differences between an Object and an Array.

JSON Objects

A JSON Object is a variable that contains one or more key-value pairs. The key is a string, and the value can be a number, another string, or even another JSON Object or Array.

For instance, consider a hypothetical weapon in a game - it has a Name, a Damage Value, an Ammunition value, and a Type. You could store all these separately, in individual properties, but you could instead store them as a JSON Object (by pairing the key - Name, Damage, Ammunition, Type - with the corresponding value for that weapon). A generic JSON object of this type, in MapTool, would look like this:

Code: Select all

{"Name":"Colt 1911", "Damage":7, "Ammunition":7, "Type":"Pistol"}
 
You can see that the values are associated with a key. To assemble that variable in MapTool, you use the Wiki: json.set() function, like so:

Code: Select all

<!--Constructing a new json, the paired curly braces indicates that you wish to create a new object-->
<!--If you want to add information to an existing JSON Object, put that objects name in place of "{}"-->

[h:weaponJSON = json.set("{}", "Name", "Colt 1911", "Damage", 10, "Ammunition", 7, "Type", "Pistol")]

<!--You could also use variables as part of the process-->
[h:wpnDam = 10]
[h:wpnName = "Colt 1911"]
[h:wpnAmmo = 7]
[h:wpnType = "Pistol"]

[h:weaponJSON = json.set("{}", "Name", wpnName, "Damage", wpnDam, "Ammunition", wpnAmmo, "Type", wpnType)]
 
So, that is creation of an object. When you need to retrieve a value from an object, you use the Wiki: json.get() function, which retrieves the value associated with a key. Suppose you stored that info in weaponJSON, and needed to retrieve it later - you would use json.get(), specifying the details you needed:

Code: Select all

[h:wpnName = json.get(weaponJSON, "Name")]
[h:wpnDam = json.get(weaponJSON, "Damage")]
[h:wpnAmmo = json.get(weaponJSON,"Ammunition")]

You hit with your [r:wpnName], dealing [r:wpnDam] damage. You have [r:wpnAmmo - 1] rounds left.
 
In short, a JSON Object lets you assign values to specific named keys, and then you can retrieve those values more or less randomly, by accessing the associated key.

Assume then, that you wanted to add another weapon to your weapon JSON Object. This poses a problem - a JSON Object only permits one instance of a key to exist in it - if you set "Name" to a new value, it will overwrite the existing value. That's bad. So, we have to have a more complex object. As mentioned already, JSON Object values can themselves be other JSON Objects. So instead of a single object looking like:

Code: Select all

{"Name":"Colt 1911", "Damage":10, "Ammunition":7, "Type":"Pistol"}
we want an object that looks like (indentation added for clarity):

Code: Select all

{"Colt 1911":
     {"Damage":10, "Ammunition":7, "Type":"Pistol"},
 "HK MP-5":
     {"Damage":8, "Ammunition":30, "Type":"SMG"}
}
This is using nested JSON objects, where the value assigned to the key "Colt 1911" is a JSON Object itself. This is a very useful technique! However, it requires a 2-step process - first you build the nested object, and then you build the "parent" object.

Code: Select all

<!-- Create the two JSONs about the individual weapons-->
[h:childJSON_1 = json.set("{}", "Damage", 10, "Ammunition", 7, "Type", "Pistol)]
[h:childJSON_2 = json.set("{}", "Damage", 8, "Ammunition", 30, "Type", "SMG")]

<!--Add them to a new JSON, the Parent object-->
[h:parentJSON = json.set("{}", "Colt 1911", childJSON_1, "HK MP-5", childJSON_2)]

<!--As a quick example, if you were adding one child, and then later added a second, you'd do it like this-->

[h:parentJSON = json.set("{}", "Colt 1911", childJSON_1)]

[h:parentJSON = json.set(parentJSON, "HK MP-5", childJSON_2)]

And you're done - the parent object now contains two values, to which are assigned individual JSON Objects that contain details about the specific weapon.

Finally, just like creating a nested JSON Object is a 2-step process, retrieving data from them using the built-in functions is likewise a 2-step process. The first step is to extract the child object from the Parent, and then extract the necessary value(s) from the Child.

Code: Select all

<!--Get the Child Object for the HK MP-5 out of the Parent JSON-->
<!--Remember, hkDetails will be a JSON Object itself-->
[h:hkDetails = json.get(parentJSON, "HK MP-5")]

<!--Get the Damage and Ammo values from the hkDetails object-->

[h:hkDmg = json.get(hkDetails,"Damage")]
[h:hkAmmo = json.get(hkDetails,"Ammo")]

You fire a burst from your HK MP-5, doing [r:hkDmg] damage. You now have [r:hkAmmo - 3] rounds left.
 

Okay, whew. That was long. I'll address Arrays in the next post. Let me know if there are any errors / ambiguities!
Last edited by Rumble on Sun Oct 31, 2010 10:40 am, edited 2 times in total.

User avatar
Rumble
Deity
Posts: 6235
Joined: Tue Jul 01, 2008 7:48 pm

Re: [MapTool] JSON Tutorials

Post by Rumble »

continued...

JSON Arrays

A JSON Array, while still part of the JSON concept, is significantly different from a JSON Object. First off, obviously, it's an array - and, much like an array in any language, it is a sequential collection of individual elements. In a JSON array, the elements can be strings, numbers, JSON Objects, or other JSON Arrays.

Second, JSON Arrays do not have keys - you access the value of an element by its index in the array, not by an associated key. Indexes start at 0, so to access the third element in an array, you access index 2.

Third, IIRC, JSON Arrays have an inherent order - that is, the order in which things are added to an array is the inherent order of the array. JSON Objects, by contrast, do not have an assumed order - the keys in an object may be in any order at any given time (so don't assume a particular order for a JSON Object!).

Finally, building a JSON Array uses Wiki: json.append() as opposed to json.set(). So, taking the weapon example, an array of weapon details might look like:

Code: Select all

["Colt 1911",10,7,"Pistol"]
In this case, you see the same information, but you have to know two things: one, the order will always be as shown, and two, you need to know (if you want to extract information from the array) that the weapon name is always at index 0, the weapon damage at index 1, ammo at index 2, and type at index 3.

To build that array, and retrieve information from it, you would use json.append() and json.get(), respectively:

Code: Select all

<!--Build the array - using "[]" indicates that you want to create a new array-->
<!--if you want to add to an existing array, put that variable name in instead of "[]"-->

[h:wpnArray = json.append("[]", "Colt 1911", 10, 7, "Pistol")]

<!--Retrieve Data-->

[h:wpnDamage = json.get(wpnArray, 1)]
 
As mentioned, JSON Arrays can hold JSON Objects as their elements, too. So remember the object we created earlier - the weapon object, that looked like this:

Code: Select all

{"Name":"Colt 1911", "Damage":10, "Ammunition":7, "Type":"Pistol"}
We could add that directly to a JSON Array like so. In fact, we could add that one, and the one for the HK MP-5, both to the same array.

Code: Select all

<!--Create the weapon JSON Objects-->

[h:coltObject = json.set("{}", "Name", "Colt 1911", "Damage", 10, "Ammunition", 7, "Type", "Pistol")]
[h:hkObject = json.set("{}", "Name", "HK MP-5", "Damage", 8, "Ammunition", 30, "Type", "SMG")]

<!--append them to the array-->

[h:weapons = json.append("[]", coltObject, hkObject)]
 
After doing all that, the JSON Array weapons looks like:

Code: Select all

[{"Name":"Colt 1911", "Damage":10, "Ammunition":7, "Type":"Pistol"}, {"Name":"HK MP-5", "Damage":8, "Ammunition":30, "Type":"SMG"}]
If you wanted to extract information from it, you again do a two-step process - first you pull the element you want out of the array, and then (since the element is a JSON object) you can pull the value out of the element by using the right key.

Code: Select all

<!--Pull out the element for HK MP-5-->
[h:hk = json.get(weapons,1)]

<!--Pull out the damage value for the HK-->
[h:hkDmg = json.get(hk, "Damage")]
 

That, in a nutshell, is how JSON Objects and JSON Arrays work. There are LOTS of tricks and uses you can put them to, but in the end they are a variable type used to store information in a couple ways - either by key-value pairing, or in a sequential array of values.

User avatar
Irrlicht
Dragon
Posts: 426
Joined: Mon Feb 09, 2009 10:53 am

Re: [MapTool] JSON Tutorials

Post by Irrlicht »

Ugh, I really appreciate your effort to answer me, but I must hope it will be more useful for other people than it is for me... sadly, I find myself lost in it as much as I do in wiki.

Let me clarify a bit: I had already understood that json objects and arrays are variable containers and the syntax (more or less) to assemble them, but the trouble comes when I try to use them.
To begin with, I'm still unable to fully understand how to retrieve a value properly.
For example, if I have the object {"WpnName":"Longsword", "Damage":1d8} I can use json.get("WpnName") to see the text Longsword in the chat box. All right.
But now I'll make it more complex, and this is where troubles start.
1) Say I use json.get("Damage"); I'll get 1d8, and I'll visualize exactly the text '1d8', not the result of a 1d8 roll. How could I get that result?
2) Say I build the object {"Weapons":{"WpnName":"Longsword", "Damage":1d8}, {"WpnName":"Great Axe", "Damage":1d12}} (if the syntax is correct); Now, what should I write exactly to get the WpnName or Damage value I'm looking for (be it either one of the two contained in the json object)?

To tell it short, I wanted to create a json object as a campaign property so that it could be a container for weapons; then a macro (call it "Create Weapon") that would be able to create other macros for given tokens; this last kind of macros would use the Strength and other pertinent properties of the token who has it in its list, and would have the other values (name, damage, range, etc.) already set, based on what I chose when using the Create Weapon macro.
I suppose I'm forced to use json to do all this, but I'm totally clueless about how.
"There are many ways my Son, to find where the souls of Demons remain...
But it takes only one second of despair and of doubt until, at last, your Soul they will gain..."

User avatar
Rumble
Deity
Posts: 6235
Joined: Tue Jul 01, 2008 7:48 pm

Re: [MapTool] JSON Tutorials

Post by Rumble »

Ah, I see - apologies for missing the real question!

Okay, so, this:
But now I'll make it more complex, and this is where troubles start.
1) Say I use json.get("Damage"); I'll get 1d8, and I'll visualize exactly the text '1d8', not the result of a 1d8 roll. How could I get that result?
First, a quick note - probably a typo on your part - remember that json.get() requires you to specify both the JSON Object you're getting from, and the key you wish to get. Your example is missing the object, it should be

Code: Select all

[json.get(weaponobject,"Damage")]
Dice rolls in maptool can be written directly, e.g. [myRoll = 1d8], and it will interpret that as you expect (rolling 1d8 and assigning that to the variable myRoll). However, if you need to store a dice roll, the only way to do so is as a string (no matter whether you're using a string property, a list, a JSON array, a JSON object, or just assigning it directly to a Token Property, saving a dice roll like 1d8 ALWAYS means saving it as a string).

And, in MapTool, the string "1d8" is not the same as the dice roll command 1d8.

Instead, what you'd need to do is retrieve the string value, and then use the Wiki: eval() function on it - that evaluates the string as if it were a macro command. So, like this:

Code: Select all


[h:wpnDamageString = json.get(weaponObject, "Damage")]

[h:actualDamage = eval(wpnDamageString)]
 
This takes the value of wpnDamageString - "1d8" - and evaluates it as if it was a command (so the eval function makes maptool "see" the string as just the 1d8 roll).
) Say I build the object {"Weapons":{"WpnName":"Longsword", "Damage":1d8}, {"WpnName":"Great Axe", "Damage":1d12}} (if the syntax is correct); Now, what should I write exactly to get the WpnName or Damage value I'm looking for (be it either one of the two contained in the json object)?
Okay, the syntax is not quite right. First, every value in a JSON Object needs it's own key - so, this object: {"WpnName":"Longsword", "Damage":"1d8"} is assigned to the key "Weapons"; however, the second object (for the greataxe) is not assigned to its key. Properly structured, the object would be something like:

Code: Select all

{"Weapon1":{"WpnName":"Longsword", "Damage":"1d8"}, "Weapon2":{"WpnName":"Great Axe", "Damage":"1d12"}}
Then, if you needed to extract a specific damage value, you'd need to do the two-step extraction sequence mentioned above: first, retrieve the proper object from the Parent JSON Object, and then retrieve the damage value from that.

Step 1: Assume we needed to get the Damage associated with Weapon2, and that the full JSON Object of all weapons is in a property called Weapons.

Code: Select all

[h:weapon2info = json.get(Weapons, "Weapon2")]
 
You now have a variable weapon2info, whose value is the following JSON Object:

Code: Select all

{"WpnName":"Great Axe", "Damage":"1d12"}
then, you need to extract the Damage value and the Weapon Name:

Code: Select all

[h:wpn2damage = json.get(weapon2info, "Damage")]
[h:wpn2name = json.get(weapon2info, "WpnName")]
 
This gives you the variable wpn2damage, whose value is "1d8". And finally, you'll evaluate that string to get an actual dice roll:

Code: Select all

[h:wpn2actualdamage = eval(wpn2damage)]
 

Finally, it may occur to you that the structure of the Weapons JSON object is a little contrived - why not, instead of saying "Weapon1" and "Weapon2" are the keys, just make the name of the weapon the key? So instead, you'd have:

Code: Select all

{"Longsword":{"Damage":"1d8", "Type":"Heavy Blade"},"Great Axe":{"Damage":1d12, "Type":"Axe"}}
Note that I added in the type bits because there's no real point in having a nested JSON object with only one key - you could just use a plain old JSON Object if there's only one interesting value (e.g., it would just be {"Longsword":"1d8", "Great Axe":"1d12"}).

Nonsapient
Cave Troll
Posts: 90
Joined: Thu Apr 23, 2009 6:37 pm

Re: [MapTool] JSON Tutorials

Post by Nonsapient »

I just want to say, Rumble, that all of this has really helped me. Thank you.

User avatar
Rumble
Deity
Posts: 6235
Joined: Tue Jul 01, 2008 7:48 pm

Re: [MapTool] JSON Tutorials

Post by Rumble »

Nonsapient wrote:I just want to say, Rumble, that all of this has really helped me. Thank you.
You're welcome - the tutorial on the wiki is pretty decent for the concept of a JSON Object/Array, i think, but they are fiddly and they will pitch vague errors when they don't work, and that can get frustrating. So I hope I've helped.

One quick note on errors: if you get "Unknown JSON type in json.get" (or in "json.fields," json.set, etc.), that means that whatever you were trying to json.get from is not a JSON object or array. Generally, that means (or it has always meant for me) one of the following:

1. Typo in a variable name in one of the json.get() calls I'm using
2. I'm using the wrong variable in the json.get() call
3. I've used the wrong key in the json.get() call - json.get() doesn't fail if you call a key that doesn't exist; it just returns an empty string (NOTE: this can also be the source of "illegal argument java.lang.string, expecting java.lang.bigDecimal" errors - you think you've extracted the key "wpnAmmo", which should have a number as a value, but the key is really named "wpnAmmunition" - extracting "wpnAmmo" returns an empty string, which causes any math operations to blow up).
4. I've forgotten the structure of the JSON Object/array I'm messing with, and the piece I think will be a JSON Object/array when extracted from its parent really isn't.

User avatar
Irrlicht
Dragon
Posts: 426
Joined: Mon Feb 09, 2009 10:53 am

Re: [MapTool] JSON Tutorials

Post by Irrlicht »

I've given only a quick look because I'm short of time at present, but it's already more clear, thanks a lot. I'll see it in full detail later.

EDIT
Alright, now the json.get is clear for me. The trouble moves to json.set and adding/removing/editing json objects (expecially json objects inside other json objects), if anyone can give some advice.
I have understood (I think) how to use json.set to create a new json object with other objects inside it, as long as it is built from zero and not tied to anything, but I've not understood how to do that when it's an already existing object, expecially if it is a campaign property.

Say I have the campaign property:
Weapons:{"Wpn1":{"Dmg":"4"}, "Wpn2":{"Dmg":"8"}}
How do I exactly add an eventual Wpn3 and how could I edit or remove either one of the Wpn1, Wpn2 or others?
"There are many ways my Son, to find where the souls of Demons remain...
But it takes only one second of despair and of doubt until, at last, your Soul they will gain..."

User avatar
Rumble
Deity
Posts: 6235
Joined: Tue Jul 01, 2008 7:48 pm

Re: [MapTool] JSON Tutorials

Post by Rumble »

Irrlicht wrote:I've given only a quick look because I'm short of time at present, but it's already more clear, thanks a lot. I'll see it in full detail later.

EDIT
Alright, now the json.get is clear for me. The trouble moves to json.set and adding/removing/editing json objects (expecially json objects inside other json objects), if anyone can give some advice.
I have understood (I think) how to use json.set to create a new json object with other objects inside it, as long as it is built from zero and not tied to anything, but I've not understood how to do that when it's an already existing object, expecially if it is a campaign property.

Say I have the campaign property:
Weapons:{"Wpn1":{"Dmg":"4"}, "Wpn2":{"Dmg":"8"}}
How do I exactly add an eventual Wpn3 and how could I edit or remove either one of the Wpn1, Wpn2 or others?
In this case you have 2 levels of nesting. If you want to add a Wpn3, you would first construct it's individual detail JSON Object:

Code: Select all

[h:wpn3_details = json.set("{}", "Dmg", 8)]
 
Then, you would need to insert that into the existing object:

Code: Select all

[Weapons = json.set(Weapons, "Wpn3", wpn3_details)]
So here, there are three things to note. First, to make sure you're setting the new key and value in an existing property, you reference that property as the first argument to json.set(). Second, you want to assign a new key, so the second argument is the name of that key - in this case, "Wpn3". Finally, you've already built the details specific to Wpn3, so you use that as the third argument in the example shown, putting a new key into the existing object.

If you wanted now to change the damage of Wpn2 to 5, you would need to do the extraction of the value associated with the key "Wpn2":

Code: Select all

[wpn2_details = json.get(Weapons, "Wpn2")]
then, you manipulate the value you want to change within the extracted JSON Object, wpn2_details:

Code: Select all

[wpn2_details = json.set(wpn2_details, "Dmg", 5)]
this says "update the existing value associated with the key 'Dmg', in the object 'wpn2_details', to a new value of 5." Note that the result of the json.set() call is assigned to the variable wpn2_details again; it's sort of like "editing in place."

Then, you can put that newly edited object back into the overall Weapons object like so:

Code: Select all

[Weapons = json.set(Weapons, "Wpn2", wpn2_details)]
So, what has been done in the final step is to update the value associated with "Wpn2" in the overall object Weapons, with the updated value of wpn2_details. Since a JSON Object can only have unique keys, the new value you want to associate with "Wpn2" overwrites the previous value associated with that key - effectively updating the object.

Bottom line is that when using json.set() and json.get() with multiply-nested JSON objects, you have to do multiple steps to drill down into the object and extract the data you need. If you change that data, you have to sequentially reassemble the object.

Raphael diSanto
Kobold
Posts: 7
Joined: Sun Oct 17, 2010 10:38 am

Re: [MapTool] JSON Tutorials

Post by Raphael diSanto »

Hi, MapTools newbie here..


This is a pretty good tutorial, but .. Nowhere (here or on the wiki) have I found out how to initialize an empty json array and then add items to it using append.

What I -want- to do is this (In pseudo-code)

MyArray = new Array()
loop (x times) {
json.append(MyArray, someval)
}

So, I figured out the looping part. The while constructor works well enough. It's not for (i=0;i<10;i++), but I can make it do what I need.

Hell, I can't even get this code to work:

[h:allDice = '[""]']
[h:json.append(allDice,"blah")]
[h:json.append(allDice,"blah2")]

But I'm not entirely sure if that's supposed to give me an array that looks like this:

["","blah","blah2"]

or one that looks like this:

["blah","blah2"]

... I'd guess the former, since I'm initializing the array with an empty string, but the documentation is somewhat unclear on this. (In that i can't even find out how to initialize an empty array to be added to later - All of the initialization examples appear to assume you already know at least some of the values that are going to go into the array)

Syntax is always the hardest part when learning a new language. Any help would be appreciated :)

Post Reply

Return to “Documentation Requests/Discussion”