Incorrect Json Parsing From REST.get

Thoughts, Help, Feature Requests, Bug Reports, Developing code for...

Moderators: dorpond, trevor, Azhrei

Forum rules
PLEASE don't post images of your entire desktop, attach entire campaign files when only a single file is needed, or generally act in some other anti-social behavior. :)
Post Reply
Rusk
Kobold
Posts: 3
Joined: Sun Jan 31, 2021 6:30 pm

Incorrect Json Parsing From REST.get

Post by Rusk »

I'm new to maptools (Just found it yesterday) and have a background in programming but this is driving me up the wall!

I'm writing some macros to create monster tokens from a REST API, hopefully all I will have to do it select it and a token will appear. But the problem is the parsing of json.get doesn't seem to work.

So i can successfully get the json into the macro.

Code: Select all

[h: baseURL = "https://5e.tools/data/bestiary"]
[h: path = "/bestiary-mm.json"]

[h: response = REST.get(baseURL + path, 0)]
[h: monsterList = json.get(response, "monster")]
but when i am trying to parse some of json objects into a token's properties it adds nothing.
For example this is an Aarakocra:

Code: Select all

{"name":"Aarakocra","source":"MM","page":12,"otherSources":[{"source":"PotA"},{"source":"SKT"},{"source":"ToA"},{"source":"EGW"},{"source":"IDRotF"}],"size":"M","type":{"type":"humanoid","tags":["aarakocra"]},"alignment":["N","G"],"ac":[12],"hp":{"average":13,"formula":"3d8"},"speed":{"walk":20,"fly":50},"str":10,"dex":14,"con":10,"int":11,"wis":12,"cha":11,"skill":{"perception":"+5"},"passive":15,"languages":["Auran","Aarakocra"],"cr":"1/4","trait":[{"name":"Dive Attack","entries":["If the aarakocra is flying and dives at least 30 feet straight toward a target and then hits it with a melee weapon attack, the attack deals an extra 3 ({@dice 1d6}) damage to the target."]}],"action":[{"name":"Talon","entries":["{@atk mw} {@hit 4} to hit, reach 5 ft., one target. {@h}4 ({@damage 1d4 + 2}) slashing damage."]},{"name":"Javelin","entries":["{@atk mw,rw} {@hit 4} to hit, reach 5 ft. or range 30/120 ft., one target. {@h}5 ({@damage 1d6 + 2}) piercing damage."]},{"name":"Summon Air Elemental","entries":["Five aarakocra within 30 feet of each other can magically summon an {@creature air elemental}. Each of the five must use its action and movement on three consecutive turns to perform an aerial dance and must maintain concentration while doing so (as if concentrating on a spell). When all five have finished their third turn of the dance, the elemental appears in an unoccupied space within 60 feet of them. It is friendly toward them and obeys their spoken commands. It remains for 1 hour, until it or all its summoners die, or until any of its summoners dismisses it as a bonus action. A summoner can't perform the dance again until it finishes a short rest. When the elemental returns to the Elemental Plane of Air, any aarakocra within 5 feet of it can return with it."]}],"environment":["mountain"],"hasToken":true,"soundClip":{"type":"internal","path":"bestiary/aarakocra.mp3"},"languageTags":["AU","OTH"],"damageTags":["P","S"],"miscTags":["MW","RW","THW"]}
I've selected the object through:

Code: Select all

[h: selectedMonster = json.get(monsterList, 0)]
This works fine and so do all the Objects with just a single value but anything that is an object or an array it parse as type UNKOWN.
For example trying to get the object "type"

Code: Select all

"type": {
                "type": "humanoid",
                "tags": [
                    "aarakocra"
                ]
            },

Code: Select all

[h: Type = json.get(selectedMonster, "type")]
When printing this out nothing is printed but when doing json.indent() it prints out the contents as

Code: Select all

 { "type": "humanoid", "tags": ["aarakocra"] }
Which is what i want. Doing json.type it is UNKOWN. This means i cannot manipulate anything and makes it 100x harder or even impossible. Am I using the wrong function or something?

I have no idea why it is refusing to parse the json to and object. Does anyone have any idea why?

Rusk

Full Code so far:

Code: Select all

[h: baseURL = "https://5e.tools/data/bestiary"]
[h: path = "/bestiary-mm.json"]

[h: response = REST.get(baseURL + path, 0)]
[h: monsterList = json.get(response, "monster")]


[h: allEntries = ""]
[h: iter = json.fields(monsterList)]

[foreach(item, iter , ""), code: {
	[h: monster = json.get(monsterList, item)]
	[h: allEntries = if(item == 0, 
	json.get(monster, "name") + ":" + item, 
	allEntries + "," + json.get(monster, "name") + ":" + item)]
}]

[h:res=input(
	"Monster|"+allEntries+"|Select A Monster: |list|value=string",
	"Number"
	)]
[h:abort(res)]

[h: selectedMonster = json.get(monsterList, listGet(stringToList(Monster, ":"), 1))]

[h: Name = json.get(selectedMonster, "name")]
[switch(json.get(selectedMonster, "size")), code:
	case "F": {
      [h: Size = "Fine"]
   };
   case "D": {
      [h: Size = "Diminutive"]
   };
   case "T": {
      [h: Size = "Tiny"]
   };
   case "S": {
      [h: Size = "Small"]
   };
   case "M": {
      [h: Size = "Medium"]
   };
   case "L": {
      [h: Size = "Large"]
   };
   case "H": {
      [h: Size = "Huge"]
   };
   case "G": {
      [h: Size = "Gargantuan"]
   };
   case "C": {
      [h: Size = "Colossal"]
   };
   default: {
      [h: Size = "Medium"]
   }
]
[r: selectedMonster]
[h: Type = json.get(selectedMonster, "type")]
[h: Alignment = json.get(selectedMonster, "alignment")]
[h: ArmourClass = json.get(selectedMonster, "ac")]
[h: AverageHP = json.get(json.get(selectedMonster, "hp"), "average")]
[h: HitDie = json.get(json.get(selectedMonster, "hp"), "formula")]
[h: WalkSpeed = json.get(json.get(selectedMonster, "speed"), "walk")]
[h: FlySpeed = json.get(json.get(selectedMonster, "speed"), "fly")]
[h: Str = json.get(selectedMonster, "str")]
[h: Dex = json.get(selectedMonster, "dex")]
[h: Con = json.get(selectedMonster, "con")]
[h: Int = json.get(selectedMonster, "int")]
[h: Wis = json.get(selectedMonster, "wis")]
[h: Cha = json.get(selectedMonster, "cha")]
[h: Saves = json.get(selectedMonster, "save")]
[h: Skills = json.get(selectedMonster, "skill")]
[h: Senses = json.get(selectedMonster, "sense")]
[h: PassivePerception = json.get(selectedMonster, "passive")]
[h: Immune = json.get(selectedMonster, "immune")]
[h: Language = json.get(selectedMonster, "languages")]
[h: CR = json.get(selectedMonster, "cr")]
[h: Traits = json.get(selectedMonster, "trait")]
[h: Actions = json.get(selectedMonster, "action")]


[h:id=findToken("MonsterBase","-Libs")]
[h:center=getViewCenter(0,";")]
[h:xCoord=getStrProp(center,"centerX")]
[h:yCoord=getStrProp(center,"centerY")]
[h:id=copyToken(id, 1, "-Libs", "{'name':'Monster','gmName':'"+Name+"','size':'"+Size+"','x':"+xCoord+",'y':"+yCoord+"}")]

[h:tokenName=getName(id)]
[h:switchToken(id)]

[h:setPropertyType("NPC")]
[h:macroList=getMacros()]

[h:setProperty("CreatureName", Name)]
[h:setProperty("CreatureSize", Size)]
[h:setProperty("Type", string(Type))]

[r: json.path.read(selectedMonster, "alignment")]
[h:setProperty("Alignment", Alignment)]

[h: hits =  eval(HitDie)]
[h:setProperty("HitPoints", hits)]

User avatar
wolph42
Winter Wolph
Posts: 9999
Joined: Fri Mar 20, 2009 5:40 am
Location: Netherlands
Contact:

Re: Incorrect Json Parsing From REST.get

Post by wolph42 »

this works:

Code: Select all

[h:monster = '{"name":"Aarakocra","source":"MM","page":12,"otherSources":[{"source":"PotA"},{"source":"SKT"},{"source":"ToA"},{"source":"EGW"},{"source":"IDRotF"}],"size":"M","type":{"type":"humanoid","tags":["aarakocra"]},"alignment":["N","G"],"ac":[12],"hp":{"average":13,"formula":"3d8"},"speed":{"walk":20,"fly":50},"str":10,"dex":14,"con":10,"int":11,"wis":12,"cha":11,"skill":{"perception":"+5"},"passive":15,"languages":["Auran","Aarakocra"],"cr":"1/4","trait":[{"name":"Dive Attack","entries":["If the aarakocra is flying and dives at least 30 feet straight toward a target and then hits it with a melee weapon attack, the attack deals an extra 3 ({@dice 1d6}) damage to the target."]}],"action":[{"name":"Talon","entries":["{@atk mw} {@hit 4} to hit, reach 5 ft., one target. {@h}4 ({@damage 1d4 + 2}) slashing damage."]},{"name":"Javelin","entries":["{@atk mw,rw} {@hit 4} to hit, reach 5 ft. or range 30/120 ft., one target. {@h}5 ({@damage 1d6 + 2}) piercing damage."]},{"name":"Summon Air Elemental","entries":["Five aarakocra within 30 feet of each other can magically summon an {@creature air elemental}. Each of the five must use its action and movement on three consecutive turns to perform an aerial dance and must maintain concentration while doing so (as if concentrating on a spell). When all five have finished their third turn of the dance, the elemental appears in an unoccupied space within 60 feet of them. It is friendly toward them and obeys their spoken commands. It remains for 1 hour, until it or all its summoners die, or until any of its summoners dismisses it as a bonus action. A summoner cant perform the dance again until it finishes a short rest. When the elemental returns to the Elemental Plane of Air, any aarakocra within 5 feet of it can return with it."]}],"environment":["mountain"],"hasToken":true,"soundClip":{"type":"internal","path":"bestiary/aarakocra.mp3"},"languageTags":["AU","OTH"],"damageTags":["P","S"],"miscTags":["MW","RW","THW"]}'] 
<pre>
[r:json.type(monster)]
[r:json.get(json.get(monster, "type"),"type")]
the big difference is the bane of MapTool... the apostrophe. In the original there is the word "can't" which contains an apostrophe, that breaks the code. Make sure to removed them before you parse them. And yes putting eg the comment somewhere in you code like <!-- this won't work --> will drive you bonkers as the macro won't work and it's impossible to pinpoint.

PS most of us (if not all) moved to discord! see link in sig.

Rusk
Kobold
Posts: 3
Joined: Sun Jan 31, 2021 6:30 pm

Re: Incorrect Json Parsing From REST.get

Post by Rusk »

Thanks so much! That's such a simple fix. Saved me so much time.

I've also joined the discord, thanks for the heads up.

Rusk

Post Reply

Return to “MapTool”