input dialog for JSON Array and JSON Object

Discuss macro implementations, ask for macro help (to share your creations, see User Creations, probably either Campaign Frameworks or Drop-in Resources).

Moderators: dorpond, trevor, Azhrei, giliath, jay, Mr.Ice

Post Reply
Holladerwaldelf
Cave Troll
Posts: 74
Joined: Fri Aug 07, 2015 1:16 pm

input dialog for JSON Array and JSON Object

Post by Holladerwaldelf »

I am saving the information for talents/abilities a character has in form of a JSON-Object, e.g.:
{ "NAME":"Ability 1" , "Attack_Bonus":10 , "Parry_Bonus":20 , "DESCRIPTION":"blablabla" , ... }
These abilities are then grouped and stored in the properties of a token in form of a JSON-Array, e.g.:
Property AbilitiesFight = [ {"NAME":"Ability 1" , ...} , {"NAME":"Ability 2" , ...} , ... ]
Property AbilitiesSocial = [ ... ]
The same system is used for the inventory of a character.
To edit the JSON-Objects/Abilities and JSON-Arrays/Properties I have written two UDFs that allow to do that with input dialogs. I am posting the code for those UDFs for two reasons: :)
a) Though the code seems to do what it is supposed to do I think it is pretty clumsy and I would appreciate any help/hints to make it more efficient/elegant.
b) If anyone is trying to do the same thing maybe the codes can help (or just be copied and used :)). And of course if you find out that it does not work in certain cases I would appreciate the feedback.

Thanks again for the help I got when I was trying to write the Object-edit-UDF.

edit object udf

Code: Select all

[h: '<!-- 	function output: Object 
			object.edit(Object object, ArrayOfKeys keysToEdit) -->']

[h: macro = "object.edit" ]
[h: arguments = "(object,keysToEdit)" ]
[h: noArgsWanted = 2]
[h: '<!-- 	variables to get a nice output for error messages -->']
[h: type = "function" ]
[h: this = getMacroLocation() ]
[h: macroName = strformat("%{this}.%{macro}%{arguments}") ]

[h: '<!-- test if number of arguments is correct -->']
	[h: noArgsInput = argCount()]
	[h: errorMessage = strformat("<b>%{type} %{macroName}</b> needs <i><b>%{noArgsWanted}</b> </i>argument(s)<i> (actual arguments:%{noArgsInput})</i>")] 
	[h: assert( noArgsInput == noArgsWanted, errorMessage ) ]

[h: '<!-- 	get the arguments -->']
[h: object = arg(0)]
	[h: errorMessage = strformat("%{type} <b>%{macroName}</b>: Object is empty.") ] 
	[h: assert ( !json.isEmpty(object), errorMessage) ]
[h: keysToEdit = arg(1) ]
	[h: errorMessage = strformat("%{type} <b>%{macroName}</b>: No Keys to edit.") ] 
	[h: assert ( !json.isEmpty(keysToEdit), errorMessage) ]

[h: '<!-- 	just some reminders of the structure of things
			object { "KEY1":"Value11", "KEY2":"Value12", "KEY3":"Value13" } 
			arrayOfKeys [ "KEY1", "KEY2", "KEY3" ] 
			[ for(counter,start,end,stepsize): command ]
			input(variableName|value|prompt|inputType|options ] -->' ]

[h: promt = " "]
[h: inputType = "TEXT" ]
[h: options = ""]

[h: inputStringList = ""]
[h: noKeysToEdit = json.length(keysToEdit)]

[h, for(i,0,noKeysToEdit,1), code: 
	{ 
	[key = json.get(keysToEdit,i) ]
		[errorMessage = strformat("%{type} <b>%{macroName}</b>: Object does not contain key.") ] 
		[assert( json.contains(object,key), errorMessage) ]
	[value = json.get(object,key) ]
	[set(key,value) ]
	[inputStringList = listAppend(inputStringList,strformat(" %{key} | %{value} | %{promt} | %{inputType} | %{options}"),"##") ]
	}]	

[h: input(inputStringList)]

[h: keysToEditVarList = json.toList(keysToEdit)]
[h: newObjectStrProp = strPropFromVars(keysToEditVarList,"UNSUFFIXED")]
[h: newObject = json.remove(json.fromStrProp(newObjectStrProp),"")]

[h: macro.return = newObject]
edit array udf

Code: Select all

[h: '<!-- 	function output: ArrayOfObjects
			array.edit(ArrayOfObjects array, ArrayOfKeys keysToEdit) -->']

[h: macro = "array.edit" ]
[h: arguments = "(array,keysToEdit)" ]
[h: noArgsWanted = 2]
[h: '<!-- 	variables to get a nice output for error messages -->']
[h: type = "function" ]
[h: this = getMacroLocation() ]
[h: macroName = strformat("%{this}.%{macro}%{arguments}") ]

[h: '<!-- test if number of arguments is correct -->']
	[h: noArgsInput = argCount()]
	[h: errorMessage = strformat("<b>%{type} %{macroName}</b> needs <i><b>%{noArgsWanted}</b> </i>argument(s)<i> (actual arguments:%{noArgsInput})</i>")] 
	[h: assert( noArgsInput == noArgsWanted, errorMessage ) ]

[h: '<!-- 	get the arguments -->']
[h: array = arg(0)]
	[h: errorMessage = strformat("%{type} <b>%{macroName}</b>: Array is empty.") ] 
	[h: assert ( !json.isEmpty(array), errorMessage) ]
[h: keysToEdit = arg(1) ]
	[h: errorMessage = strformat("%{type} <b>%{macroName}</b>: No Keys to edit.") ] 
	[h: assert ( !json.isEmpty(keysToEdit), errorMessage) ]

[h: '<!-- 	just some reminders of the structure of things
			arrayOfObjects [ object1, object2, object2 ]
			object { "KEY1":"Value11", "KEY2":"Value12", "KEY3":"Value13" } 
			arrayOfKeys [ "KEY1", "KEY2", "KEY3" ] 
			[ for(counter,start,end,stepsize): command ]
			input(variableName|value|prompt|inputType|options ] -->' ]

[h: noObjects = json.length(array) ]
[h: noKeysToEdit = json.length(keysToEdit)]			

[h: '<-- 	outer loop: create a tab for each Object, variableName is tabVar%{i} -->']
[h: inputStringList = ""]
[h: promt = " "]
[h: options = ""]
[h: tabVarList = ""]
[h, for(i,0,noObjects,1), code:
	{
	[inputType = "TAB" ]
	[tabVar = strformat("tabVar%{i}")]
	[tabVarList = listAppend(tabVarList,tabVar)]
	[tabLabel = strformat("Object%{i}") ]
	[inputStringList = listAppend(inputStringList,strformat(" %{tabVar} | %{tabLabel} | %{promt} | %{inputType} | %{options}"),"##") ]
	['<-- 	inner loop: create text fields for the Keys of the object -->']
	[inputType = "TEXT" ]
	[promt = " "]
	[options = ""]
	[object = json.get(array,i)]
	[for(j,0,noKeysToEdit,1), code: 
		{ 
		[key = json.get(keysToEdit,j) ]
			[errorMessage = strformat("Object does not contain key.") ] 
			[assert( json.contains(object,key), errorMessage) ]	
		[value = json.get(object,key) ]
		[set(key,value) ]
		[inputStringList = listAppend(inputStringList,strformat(" %{key} | %{value} | %{promt} | %{inputType} | %{options}"),"##") ]
		}]	
	}]

[h: input(inputStringList)]
[h: '<!-- 	input() gets StringPropertyLists as values for the tabVars
				tabVar0 = "KEY1=newValueA1,KEY2="newValueA2,KEY3=newValueA3"
				tabVar1 = "KEY1=newValueB1,KEY2="newValueB2,KEY3=newValueB3"
				tabVar3 = "KEY1=newValueC1,KEY2="newValueC2,KEY3=newValueC3" 
			the names of the tabVars have been saved to tabVarList (in form of a StringList)
				tabVarList = "tabVar0, tabVar1, tabVar2" -->']

[h: '<!-- 	strPropFromVars() puts the values of the tabVars in a StringPropertyList
				inputAsStrPropList =  "	tabVar0 = KEY1=newValueA1 ## KEY2=newValueA2 ## KEY3=newValueA3 ## ; 
										tabVar1 = KEY1=newValueB1 ## KEY2=newValueB2 ## KEY3=newValueB3 ## ; 
										tabVar2 = KEY1=newValueC1 ## KEY2=newValueC2 ## KEY3=newValueC3 ## ;" -->']
[h: inputAsStrPropList = strPropFromVars(tabVarList,"UNSUFFIXED")]
[h: '<!-- 	json.fromStrProp() converts the StrPropList into a jsonObject
				inputAsJsonObj =  {	"tabVar0":"KEY1=newValueA1 ## KEY2=newValueA2 ## KEY3=newValueA3 ##",
									"tabVar1":"KEY1=newValueB1 ## KEY2=newValueB2 ## KEY3=newValueB3 ##",
									"tabVar2":"KEY1=newValueC1 ## KEY2=newValueC2 ## KEY3=newValueC3 ##" } -->']
[h: inputAsJsonObj = json.remove(json.fromStrProp(inputAsStrPropList,";"),"")]
				
[h: arrayOut = array]
[h, for(i,0,noObjects,1), code:
	{
	['<!-- json.get() gets the oldObject out of the original array
			oldObject = { "KEY1":"ValueA1", "KEY2":"ValueA2", "KEY3":"ValueA3" } [i=0] -->']
	[oldObject = json.get(arrayOut,i)]
	['<!-- json.get() gets the new values in form of a StrPropList
			inputObjectStrPropList =  "KEY1=newValueA1 ## KEY2=newValueA2 ## KEY3=newValueA3 ##" [i=0] -->' ]
	[inputObjectStrPropList = json.get(inputAsJsonObj,strformat("tabVar%{i}"))]
	['<!-- json.fromStringProp() converts the StrPropList into a jsonObject
			inputObject = { "KEY1":"newValueA1", "KEY2":"newValueA2", "KEY3":"newValueA3" } [i=0] -->']
	[inputObject = json.remove(json.fromStrProp(inputObjectStrPropList,"##"),"")]
	['<!-- json.merge() merges the inputObject with the oldObject, 
		in case some keyValues have not been edited they will still appear in the newObject
			newObject = { "KEY1":"newValueA1", "KEY2":"newValueA2", "KEY3":"newValueA3" } [i=0] -->']
	[newObject = json.merge(oldObject,inputObject)]
	['<!-- json.set() puts the newObject in place of the old object in the output array -->']
	[arrayOut = json.set(arrayOut,i,newObject)]
	}]
	
[h: macro.return = arrayOut]	

And two macros that might help fiddling around with the UDFs:
test edit.object

Code: Select all

[h: '<!-- 	macro tests function
			object.edit(object,keysToEdit) -->']

[h: object =json.set("", "KEY1", "Value1", "KEY2", "Value2", "KEY3", "Value3") ]
[h: keysToEdit = json.append("", "KEY1", "KEY2", "KEY3") ]

[h: newObject = object.edit(object,keysToEdit) ]

<b><u>Test:</u> function LIB:JSON object.edit(object,keysToEdit)</b><br>
<i>input: object =</i> [r:object]<br>
<i>keysToEdit = </i> [r:keysToEdit] <br>
<i>output = </i> [r:newObject]
test edit.array

Code: Select all

[h: '<!-- 	macro tests function
			array.edit(array,keysToEdit) -->']

[h: objectA =json.set("", "KEY1", "A1", "KEY2", "A2", "KEY3", "A3") ]
[h: objectB =json.set("", "KEY1", "B1", "KEY2", "B2", "KEY3", "B3") ]
[h: objectC =json.set("", "KEY1", "C1", "KEY2", "C2", "KEY3", "C3") ]
[h: array = json.append("",objectA,objectB,objectC) ]
[h: keysToEdit = json.append("", "KEY1", "KEY2", "KEY3") ]

[h: newArray = array.edit(array,keysToEdit) ]

<b><u>Test:</u> function LIB:JSON array.edit(array,keysToEdit)</b><br>
<i>input: array is</i> [r:array]<br>
<i>keysToEdit is</i> [r:keysToEdit] <br>
<i>output is </i> [r:newArray]

Post Reply

Return to “Macros”