WinBatch® Technical Support Forum

All Things WinBatch => WinBatch => Topic started by: kdmoyers on August 29, 2025, 11:50:57 AM

Title: best attempt at jsValueGet wrapper
Post by: kdmoyers on August 29, 2025, 11:50:57 AM
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
Title: Re: best attempt at jsValueGet wrapper
Post by: JTaylor on August 29, 2025, 03:04:06 PM

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
Title: Re: best attempt at jsValueGet wrapper
Post by: td on September 02, 2025, 08:25:30 AM
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