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