Page 1 of 1

Searching for Json elements...

Posted: Mon Jun 06, 2022 5:29 pm
by Michael Vogel
Hi,
I need to parse json configuration files to find certain elements, so I started to create 'JsonScan' which is doing that stuff and return the found element type or -1 if the search fails. The example shows a file of the Garmin IQ SDK which allows to write programs for their sport watches.

JsonScan(object,"name") will return the object 'name' if found, where name may also include the hierarchical path to the object (like 'display/location/width').

I haven't implemented all Json types but beside standard objects the following types are supported: numbers, strings and arrays. For arrays, the index of the array could also be used in the object path, like in 'keys/1/location/width'.

Code: Select all


jsonfile.s="{|'display': {|'behaviors': [],|'isTouch': false,|'landscapeOrientation': 0,|'location': {|'height': 240,|'width': 240,|'x': 105,|'y': 145|},|'shape': 'round'|},|'fonts': [|{|'fontSet': 'ww',|'fonts': [|{|'filename': 'FNT_FENIX5_CHRONOSSEMIBOLDCONDENSED_58PX',|'name': 'systemNumberThaiHot'|}|]|},|{|'fontSet': 'apac_jpn',|'fonts': [|{|'filename': 'FNT_FENIX5_CHRONOSSEMIBOLDCONDENSED_58PX',|'name': 'systemNumberThaiHot'|}|]|},|{|'fontSet': 'apac_tha',|'fonts': [|{|'filename': 'bitstreamVeraSans 16',|'name': 'xtiny'|},|{|'filename': 'FNT_FENIX5_CHRONOSSEMIBOLDCONDENSED_58PX',|'name': 'systemNumberThaiHot'|}|]|}|],|'image': 'forerunner_935.png',|'keys': [|{|'behavior': 'onSelect',|'id': 'enter',|'location': {|'height': 52,|'width': 38,|'x': 377,|'y': 165|}|},|{|'behavior': 'previousPage',|'id': 'up',|'location': {|'height': 57,|'width': 25,|'x': 25,|'y': 244|}|},|{|'behavior': 'onMenu',|'id': 'menu',|'isHold': true,|'location': {|'height': 57,|'width': 25,|'x': 25,|'y': 244|}|},|{|'behavior': 'nextPage',|'id': 'down',|'location': {|'height': 52,|'width': 32,|'x': 41,|'y': 327|}|},|{|'id': 'clock',|'isHold': true,|'location': {|'height': 52,|'width': 32,|'x': 41,|'y': 327|}|},|{|'behavior': 'onBack',|'id': 'esc',|'location': {|'height': 60,|'width': 33,|'x': 376,|'y': 321|}|}|],|'layouts': [|{|'datafields': {|'datafields': [|{|'drawBorders': true,|'fields': [|{|'data': {|'font': 'numberThaiHot',|'justification': 'center',|'width': 192,|'x': 119,|'y': 157|},|'obscurity': [|'left',|'top',|'right',|'bottom'|]|}|],|'name': '1 Field'|},|{|'drawBorders': true,|'fields': [|{|'data': {|'font': 'numberThaiHot',|'justification': 'center',|'width': 154,|'x': 120,|'y': 115|},|'label': {|'font': 'tiny',|'justification': 'center',|'x': 119,|'y': 47|},|'labelDisabled': false,|'location': {|'height': 119,|'width': 240,|'x': 0,|'y': 0|},|'obscurity': [|'left',|'top',|'right'|]|},|{|'data': {|'font': 'numberThaiHot',|'justification': 'center',|'width': 154,|'x': 120,|'y': 89|},|'label': {|'font': 'tiny',|'justification': 'center',|'x': 119,|'y': 22|},|'labelDisabled': false,|'location': {|'height': 119,|'width': 240,|'x': 0,|'y': 121|},|'obscurity': [|'left',|'right',|'bottom'|]|}|],|'name': '2 Fields'|},|{|'drawBorders': true,|'fields': [|{|'data': {|'font': 'numberMedium',|'justification': 'center',|'width': 132,|'x': 120,|'y': 74|},|'label': {|'font': 'tiny',|'justification': 'center',|'x': 119,|'y': 29|},|'labelDisabled': false,|'location': {|'height': 77,|'width': 240,|'x': 0,|'y': 0|},|'obscurity': [|'left',|'top',|'right'|]|},|{|'data': {|'font': 'numberMild',|'justification': 'center',|'width': 96,|'x': 54,|'y': 62|},|'label': {|'font': 'tiny',|'justification': 'center',|'x': 54,|'y': 23|},|'labelDisabled': false,|'location': {|'height': 119,|'width': 119,|'x': 121,|'y': 121|},|'obscurity': [|'right',|'bottom'|]|}|],|'name': '4 Fields B'|}|]|},|'menu2': {|'customTitle': {|'height': 52,|'width': 126,|'x': 57,|'y': 18|},|'doneButtons': {|'bottom': true,|'top': true|},|'items': {|'checks': [|{|'alignment': 'left',|'disabledIconFile': 'menu2_check_off_vegas.png',|'enabledIconFile': 'menu2_check_on_vegas.png',|'x': 11,|'y': 32|},|{|'alignment': 'right',|'disabledIconFile': 'menu2_check_off_vegas.png',|'enabledIconFile': 'menu2_check_on_vegas.png',|'x': 199,|'y': 32|}|],|'icons': {|'check': 'left',|'icon': 'left',|'leftLocation': {|'height': 82,|'width': 41,|'x': 3,|'y': 7|},|'rightLocation': {|'height': 82,|'width': 41,|'x': 196,|'y': 7|},|'toggle': 'right'|},|'item': {|'height': 96,|'labelFont': 'large',|'subLabelFont': 'small',|'width': 240|},|'region': {|'height': 96,|'width': 240,|'x': 0,|'y': 72|},|'stringWidths': {|'basic': 224,|'check': 152,|'icon': 152,|'toggle': 200|},|'subItem': {|'height': 51,|'labelFont': 'tiny',|'labelWidth': 178,|'yOffset': 2|},|'toggles': [|{|'alignment': 'left',|'disabledIconFile': 'menu2_toggle_off_left_240x240.png',|'enabledIconFile': 'menu2_toggle_on_left_240x240.png',|'x': 3,|'y': 7|},|{|'alignment': 'right',|'disabledIconFile': 'menu2_toggle_off_right_240x240.png',|'enabledIconFile': 'menu2_toggle_on_right_240x240.png',|'x': 220,|'y': 7|}|]|},|'title': {|'height': 72,|'width': 240,|'x': 0,|'y': 0|},|'titleString': {|'font': 'tiny',|'width': 120,|'x': 119,|'y': 42|}|},|'orientation': 'portrait',|'picker': {|'entries': [|{|'height': 132,|'width': 65,|'x': 11,|'y': 80|},|{|'height': 132,|'width': 65,|'x': 87,|'y': 80|},|{|'height': 132,|'width': 65,|'x': 164,|'y': 80|}|],|'title': {|'height': 66,|'width': 240,|'x': 0,|'y': 0|}|}|}|],|'sensorHistory': [|{|'interval': 120,|'size': 120,|'type': 'heartrate'|},|{|'interval': 72,|'size': 200,|'type': 'elevation'|},|{|'interval': 72,|'size': 200,|'type': 'temperature'|},|{|'interval': 72,|'size': 200,|'type': 'pressure'|}|],|'watchdogCount': 120000|}"

jsonfile=ReplaceString(jsonfile,"'",#DOUBLEQUOTE$)
jsonfile=ReplaceString(jsonfile,"|",#CRLF$)



Structure JsonType
	parent.i
	object.i
	name.s
	valtext.s
	valnumber.i
	type.i
	depth.i
EndStructure

Global Jay.JsonType

#Undefined=		-#True
#Seperator=		"/"

Macro JsonFound(okay)

	If depth=CountString(object,#Seperator)+1
		Jay\name=JSONMemberKey(json)
		Jay\object=JSONMemberValue(json)
		Jay\type=JSONType(Jay\object)
		Jay\valtext=""
		Jay\valnumber=#Null

		; Debug "type "+Jay\type
		Select Jay\type
		Case #PB_JSON_Number
			Jay\valnumber=GetJSONInteger(Jay\object)
		Case #PB_JSON_String
			Jay\valtext=GetJSONString(Jay\object)
		Case #PB_JSON_Array
			Jay\valnumber=JSONArraySize(Jay\object)
		Default
			Debug "Other type: "+Str(Jay\type)
		EndSelect

		ProcedureReturn Jay\type

	ElseIf JSONType(json)=#PB_JSON_Object

		If okay=0
			json=JSONMemberValue(json)
		EndIf
		ProcedureReturn JsonScan(json,object,depth)

	Else
		Debug "error"

	EndIf

EndMacro
Procedure JsonScan(json,object.s,depth=#Null)

	Protected o
	Protected check.s

	;Debug "=== "+depth+" ===  "+json

	With Jay

		If json
			\parent=json
			depth+1

			Select JSONType(json)

			Case #PB_JSON_Object
				check=StringField(object,depth,#Seperator)
				If ExamineJSONMembers(json)

					While NextJSONMember(json)
						;Debug "> "+JSONMemberKey(json)
						If JSONType(JSONMemberValue(json))
						EndIf

						If JSONMemberKey(json)=check
							JsonFound(0)
						EndIf

					Wend
				EndIf

			Case #PB_JSON_Array
				;Debug ">>>> "+StringField(object,depth,#Seperator)
				json=GetJSONElement(json,Val(StringField(object,depth,#Seperator))-1)
				If json
					JsonFound(1)
				EndIf
				Debug "Hm.."

			EndSelect

		Else
			\parent=#Null
			ProcedureReturn #Null

		EndIf

	EndWith

EndProcedure


;n=LoadJSON(0,s,#PB_JSON_NoCase)
n=ParseJSON(0,jsonfile,#PB_JSON_NoCase)
If n
	n=JSONValue(0)

	If JsonScan(n,"display/location/width")=#PB_JSON_Number
		Debug jay\name+" = "+Str(jay\valnumber)
	EndIf
	If JsonScan(n,"display/location/height")=#PB_JSON_Number
		Debug jay\name+" = "+Str(jay\valnumber)
	EndIf
	If JsonScan(n,"display/shape")=#PB_JSON_String
		Debug jay\name+" = "+jay\valtext
	EndIf
	If JsonScan(n,"display/location/x")=#PB_JSON_Number
		Debug jay\name+" = "+Str(jay\valnumber)
	EndIf
	If JsonScan(n,"display/location/y")=#PB_JSON_Number
		Debug jay\name+" = "+Str(jay\valnumber)
	EndIf

	If JsonScan(n,"keys")=#PB_JSON_Array
		z=jay\valnumber
		For i=1 To z
			If JsonScan(n,"keys/"+Str(i)+"/id")=#PB_JSON_String
				Debug jay\valtext
				If JsonScan(n,"keys/"+Str(i)+"/location/height")=#PB_JSON_Number
					Debug jay\name+" = "+Str(jay\valnumber)
				EndIf
				If JsonScan(n,"keys/"+Str(i)+"/location/width")=#PB_JSON_Number
					Debug jay\name+" = "+Str(jay\valnumber)
				EndIf
			EndIf
		Next i
		Debug "ok"
	EndIf

	If ExamineJSONMembers(n)
		While NextJSONMember(n)
			;Debug JSONMemberKey(n) + " = " ;+ GetJSONInteger(JSONMemberValue(n))
			If JSONType(n)=#PB_JSON_Array
				;Debug "*"
			EndIf
		Wend
	EndIf
EndIf