I'm betting some of you guys already have a wrapper for jsValueGet that provides a default for missing values. I have my attempts (below) but I'm wondering if you have better ones.
; JSON data as a multi-line string constant.
JsonData = $"{
"dependencies":: {
"Microsoft.NETCore.UniversalWindowsPlatform":: "5.2.2",
},
"frameworks":: {
"uap10.0":: {},
"spot":: 45
},
"speed":: 30,
"runtimes":: {
"win10-arm":: {},
"speed"::55,
"win10-x64-aot":: {}
}
}$"
jh = jsParse(jsondata)
; this one is cleanest, but fails test 5
#definefunction jsValueGetOrDefX (handle,key,default)
if !jsKeyExist(handle,key) then return default
return jsValueGet(handle,key,".")
#endfunction
; this one exploits error recovery, but passes all tests
#definefunction jsValueGetOrDefault (handle,key,default)
lasterror()
errormode(@off)
z = jsValueGet(handle,key,".")
errormode(@on)
w = lasterror()
if w == 0 then return z ; no error? just return the answer
if w == 20108 then return default ; key-not-found error? return default
terminate(1,'jsValueGet error',w) ; some other error
#endfunction
; this is a hot mess, but it passes all tests
#definefunction jsValueGetOrDefXX (handle,key,default)
arr = jsKeyPaths(handle,key,".")
if arrinfo(arr,1) == 0
return default
endif
path = strclean(arr[0],"[]","",@true,1)
if path == key
return jsValueGet(handle,key,".")
else
return default
endif
#endfunction
message("test 1", jsValueGetOrDefault(jh, "runtimes.speed", "none") ) ; should be 55
message("test 2", jsValueGetOrDefault(jh, "speed", "none") ) ; should be 30
message("test 3", jsValueGetOrDefault(jh, "XspeXed", "none") ) ; should be none
message("test 4", jsValueGetOrDefault(jh, "frameworks.spot","none") ) ; should be 45
message("test 5", jsValueGetOrDefault(jh, "spot", "none") ) ; should be none
exit
I sometimes use the below. Since I just folded my JSON parsing into the WebView Extender it has that as part of the function options so I would probably be using it most of the time now anyway. I am sure Tony is going to add a default parameter as a feature soon though so we don't have to come up with ways around this VERY COMMON problem ;-)
IntControl(73, 2, @TRUE, 1, 0)
:WBERRORHANDLER
If StrTrim(ItemExtract(1,wberrortextstring,":")) == 20108 Then
%wberroradditionalinfo% = ""
EndIf
IntControl(73, 2, @TRUE, 1, 0)
Return
Jim
Just use jsTypeGet. It returns 0 when the passed in key does not exist. Of course, you would need to download the latest version of the extender first.
Also, the proper way to use the jsKeyExist function is to pass it a pointer. For example,
; this one is cleanest and no longer fails test 5
#definefunction jsValueGetOrDefX (handle,key,default)
if !jsKeyExist(handle,key, &paths) then return default
return jsValueGet(handle,paths[0])
#endfunction