best attempt at jsValueGet wrapper

Started by kdmoyers, August 29, 2025, 11:50:57 AM

Previous topic - Next topic

kdmoyers

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
The mind is everything; What you think, you become.

JTaylor


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

td

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
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

SMF spam blocked by CleanTalk