bmceldowney wrote:...
The problem that I keep running into is that it is impossible for me to tell whether or not there is already a
JSON Array assigned to the property.
Wiki: json.type() won't tell me if weaponProperty contains a
JSON Array or not (returns UNKNOWN regardless of what the value of my property is), and if there is a
JSON Array already there then the
Wiki: if() statement throws an invalid condition error.
Is there a better mousetrap for this quandary?
I'm not exactly sure what the problem is, but I've never had a problem with json.type() not returning the correct type, especially after storing the property value via
Wiki: getProperty(). Have you tried to output the actual value that you are sending to json.type(), just to verify that it is, in fact a valid json as you expect? Sometimes weird things happen and if the format gets screwed up, json.type may no longer recognize it.
I also noticed you are passing
Wiki: getSelected() directly in the call to getProperty, which I see as being a little dangerous: getSelected can return a list if more than one token is selected ; You are probably better off processing getSelected() to ensure you are dealing with only one token, and maybe even switching token context (
Wiki: switchToken()) to avoid unexpected surprises.
Also, this is a commonly used check, which I never use anymore:
because it goes haywire if the variable value is a json, due to some peculiarities of data types in MapTool:
- JSONs are not strings (therefore you can not compare them to a string or similar data types: see Wiki: json.equals() for methods to compare JSONs).
- an empty string ("") also qualifies as an empty JSON (returns TRUE/1 if passed to Wiki: json.isEmpty() ), but is of type "UNKNOWN" (Wiki: json.type() returns "UNKNOWN").
- JSONs are stored as strings in token properties (due to technicalities of the way property data is stored on a token): in terms of Macro Script, this is rarely an issue (more a performance issue owing to the need to convert JSONs to/from strings when writing/fetching from a token property).
- JSONs can be easily converted to strings using the Wiki: string() function.
Therefore, some alternatives to the above check include:
Code: Select all
[IF( string(variable)=="" ): code ] <!-- now you are always comparing a string to a string -->
[IF( json.type(variable)=="UNKNOWN" ): code ]<!-- will catch empty strings, and anything not a valid json object or array. -->
Note I do not trust this kind of check:
Code: Select all
[IF( json.isEmpty(variable) ): code ]
Because
Wiki: json.isEmpty() is not always reliable for this sort of thing: it will return 0 (not an empty json) for a string starting and ending with the right characters ("[]" or "{}"), even if the rest is not a valid JSON structure: e.g. "{foo}" returns 0 for json.isEmpty, but returns a NullPointerException error from json.type, or other json functions.
A few other points about data types in MapTool, in case anyone's interested:
- numbers can be treated as strings, but strings aren't necessarily numbers.
- numbers stored as, or extracted from strings often (but not always) revert to being numbers. For example, strformat( "%+d" , 4 ) produces a string ("+2"), but if you try to output that number, or concatenate it to other strings, all you get is "2".
- strformat( " %+d" , 4 ) produces a string (" +2"), notice the leading space, which remains as " +2" on output, but:
- qualifies as a number (Wiki: isNumber() returns TRUE/1),
- but throw errors if you try to do math with it.
- It can easily be converted to a number, but comes out as a floating-point value with many decimal places (many of which are 0), unless you convert to an integer using Wiki: floor(). (Wiki: number()).
That was probably way more information that you wanted, but I felt like laying it all out there anyway.