I was sure I'd find some examples of consuming a REST api in the tech database, but I'm coming up empty. What should I be searching for?
Restful calls usually return json. I know I have posted several examples. Whether or not they got to Tech DB would be up to Tony. But for fun try below and check return
cUrl = "https://query1.finance.yahoo.com/v7/finance/quote?symbols=IBM,GOOG,AAPL"
request = Createobject("WinHttp.WinHttpRequest.5.1")
request.Open("GET", cUrl, @False )
request.Send()
json = request.ResponseText
ObjectClose(request)
I am not sure how to answer that one. There are several examples, but they tend to be associated with specific tasks. I know Stan has posted examples over the years. Many REST API providers have examples in Curl. Curl translations to WIL are generally straightforward.
REST API usage typically involves a combination of POST and GET HTTP verbs, utilizing JSON as the data format. HTTP headers are almost always required as well.
I imagine you already know HTTP and HTML basics, but this longish tutorial is a good way to brush up.
https://techsupt.winbatch.com/webcgi/webbatch.exe?techsupt/nftechsupt.web+Tutorials+HTTP~and~WinInet~-~An~Opus.txt (https://techsupt.winbatch.com/webcgi/webbatch.exe?techsupt/nftechsupt.web+Tutorials+HTTP~and~WinInet~-~An~Opus.txt)
Here is a dummy example that may be of some use:
objHttp=ObjectCreate("Msxml2.XMLHTTP.6.0") ;WinHttp.WinHttpRequest.5.1") ; MSFT keeps Msxml2 in better shape.
URL = "https://your.api.url.here/maybe some more required here"
objHttp.open("POST",URL,"False")
objHttp.SetRequestHeader("Authorization", "Bobs-Auth-Key some long 64bit number or something here" ) ; Put your key here!
objHttp.SetRequestHeader("User-Agent", "MyApp/1.1.1") ; Put your "app" name here!
objHttp.SetRequestHeader("Content-Length", "71") ; Set the data length in bytes here
objHttp.SetRequestHeader("Accept", "application/json")
objHttp.SetRequestHeader("Content-Type", "application/json")
Body = `{"whatever":["some json key":some json value}`
objHttp.Send(body)
while objHttp.readyState != 4
objHttp.WaitForResponse(10)
endwhile
Terminate(objHttp.Status != 200,"REST API", "You didn't do it correctly or the server is down")
strJson=objHttp.responseText
; You can use the JSON extender to extract the returned results.
This forum likely has a few better examples, if you can find them.
and for more fun, here is an older script (probably pre-dates Json Extender, when ScriptControl object could be used to parse Json). Uses CLR instead of COM.
;Based on Tony's code to obtain Yahoo finance for multiple stocks; returns Json
IntControl(73,1,0,0,0)
Gosub udfs
symbols = "IBM,GOOG,AAPL"
strUrl = "https://query1.finance.yahoo.com/v7/finance/quote?symbols=%symbols%"
ObjectClrOption('useany', 'System')
objWebUtil = ObjectClrNew('System.Net.WebUtility')
objUri = ObjectClrNew('System.Uri', strUrl)
objSvcManager = ObjectClrNew('System.Net.ServicePointManager')
protocols = ObjectClrType("System.Net.SecurityProtocolType",3072|768)
objSvcManager.SecurityProtocol = protocols
objSvcPoint = objSvcManager.FindServicePoint(objUri)
objWebRequest = ObjectClrNew('System.Net.WebRequest')
objWebRequest = objWebRequest.Create(objUri)
objWebRequest.Timeout = objWebRequest.Timeout * 5
objResponse = objWebRequest.GetResponse()
objResponseStream = objResponse.GetResponseStream
Encoding = ObjectClrNew( 'System.Text.Encoding' )
objStreamReader = ObjectClrNew("System.IO.StreamReader", objResponseStream, Encoding.UTF8)
;convert json to comma-delimited file
strOut = 'c:\temp\Output.Json'
if FileExist(strOut) then FileDelete(strOut)
jdata = StrReplace(objStreamReader.ReadToEnd(),",",",":@LF)
Message("",Jlen(jdata))
output = GetJSON1(jdata)
hdr = "Key":@TAB:"Subkey":@TAB:"Value":@LF
output = hdr:StrReplace(output,",",@TAB) ;change to Tab-delimited
FilePut(strOut, StrReplace (output, @LF, @CRLF))
if FileExist(strOut) then Display(2,'Json Data', strOut)
if FileExist(strOut) then Run('notepad.exe', strOut)
Exit
;=========================================================================================
:WBERRORHANDLER
Terminate(@TRUE,"Error Encountered",err())
:udfs
#DefineFunction err()
wberroradditionalinfo = wberrorarray[6]
lasterr = wberrorarray[0]
handlerline = wberrorarray[1]
textstring = wberrorarray[5]
linenumber = wberrorarray[8]
errmsg = "Error: ":lasterr:@LF:textstring:@LF:"Line (":linenumber:")":@LF:wberroradditionalinfo
Return(errmsg)
#EndFunction
#DefineFunction GetJSON(jdata)
If jdata == "" Then Return ""
objJSC = CreateObject ("MSScriptControl.ScriptControl")
objJSC.Language = "JScript"
;objJSC.AddCode(: `function json2txt(obj,path){var txt='';for(var key in obj){if(obj.hasOwnProperty(key)){if('object'==typeof(obj[key])){txt+=json2txt(obj[key],path+(path?'|':'')+key);}else{txt+=path+'|'+key+','+obj[key]+'\n';}}}return txt;}`)
code = $"
function json2txt(obj)
{
var txt = '';
var recurse = function(_obj) {
if ('object' != typeof(_obj)) {
txt += ',' + _obj + '\n';
}
else {
for (var key in _obj) {
if (_obj.hasOwnProperty(key)) {
txt += key;
recurse(_obj[key]);
}
}
}
};
recurse(obj);
return txt;
}
$"
objJSC.AddCode(:code)
Return objJSC.Eval(: `json2txt(` : jdata : `,'')`)
; JS code from Patrick Fisher at "http://stackoverflow.com/questions/10221229/list-all-keys-and-values-of-json" ; 2012-04-19T03:48:24.
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction Keys(jdata)
If jdata == "" Then Return ""
objJSC = CreateObject ("MSScriptControl.ScriptControl")
objJSC.Language = "JScript"
objJSC.AddCode(: `function getKeys(obj,path){ var keys = new Array(); for (var i in obj) { keys.push(i); } return keys; }`)
Return objJSC.Eval(: `getKeys(` : jdata : `,'')`)
#EndFunction
#DefineFunction JSONDecode(jdata)
objJSC = CreateObject ("MSScriptControl.ScriptControl")
objJSC.Language = "JScript"
data = objJSC.Eval(: `(` : jdata : `)` )
Return(data)
#EndFunction
#DefineFunction Jlen(jdata)
objJSC = CreateObject ("MSScriptControl.ScriptControl")
objJSC.Language = "JScript"
code = $"
function Keylen(jsonObj) {
var keys = '';
for (var n in jsonObj) {
keys += n + '|' ; }
return keys;
}
$"
objJSC.AddCode(:code)
Return objJSC.Eval(: `Keylen(` : jdata : `,'')`)
#EndFunction
#DefineFunction UnixDate(d,ms)
If ms Then d="00":d
Ymd = TimeAdd('1970:01:01:00:00:00', d)
Ymd = TimeFormat(Ymd,"MM/dd/yyyy")
Return(Ymd)
#EndFunction
#DefineFunction GetJSON1(jdata)
If jdata == "" Then Return ""
objJSC = CreateObject ("MSScriptControl.ScriptControl")
objJSC.Language = "JScript"
code = $"
function json2txt(obj,path){
var txt='';
for(var key in obj){
if(obj.hasOwnProperty(key)){
if('object'==typeof(obj[key])){
txt += json2txt(obj[key],path+(path?''::'')+key);}
else{txt+=path+','+key+','+obj[key]+'\n';}
}
}
return txt;
}
$"
objJSC.AddCode(:code)
Return objJSC.Eval(: `json2txt(` : jdata : `,'')`)
; JS code from Patrick Fisher at "http://stackoverflow.com/questions/10221229/list-all-keys-and-values-of-json" ; 2012-04-19T03:48:24.
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
Return
As PS has Invoke-RestMethod as a cmdlet, here is the simplest STD_Out script I could put together in 2-3 minutes to illustrate.
OT: but if you think about it, I have posted multiple Std_out scripts all with the same scenario
- WB upfront code to create variables/input or output file
- Simple argument variable with replace calls if needed
- Single UDF for results
Now if the single UDF could be called from a data source holding fields for Description of Process; the argument; the list of replace; and the outcome... easy to create a dropdown list for conversions involving
db sources
csv
excel
json
xml
yaml
into a single script. {I've thought about it}
;Rest Query for IP Address
;Stan Littlefield 7/8/2025
;==========================================================
Gosub udfs
args = $"
$IPAddress = (curl -uri "http:://ifconfig.me/ip").Content
$LocationInfo = Invoke-RestMethod -Method Get -Uri "http:://ip-api.com/json/$IPAddress"
$LocationInfo
$"
cmd="Powershell"
msg='IP Address
BoxOpen("Running...",cmd:" ":args:@LF:"PLEASE WAIT...MAY TAKE SOME TIME")
TimeDelay(2)
vals = Get_stdout():@LF:"Script Completed"
Message(msg,vals)
;If FileExist(xml) Then Run("notepad.exe",xml)
Exit
;==========================================================
:udfs
#DefineSubroutine Get_stdout()
ObjectClrOption("useany","System")
objInfo = ObjectClrNew("System.Diagnostics.ProcessStartInfo")
Output=""
timeOut = ObjectType("I2",5000)
objInfo.FileName = cmd
objInfo.RedirectStandardError = ObjectType("BOOL",@TRUE)
objInfo.RedirectStandardOutput = ObjectType("BOOL",@TRUE)
objInfo.UseShellExecute = ObjectType("BOOL",@FALSE)
objInfo.CreateNoWindow = ObjectType("BOOL",@TRUE)
objInfo.Arguments = args
oProcess = ObjectClrNew("System.Diagnostics.Process")
oProcess.StartInfo = objInfo
BoxShut()
oProcess.Start()
oProcess.WaitForExit(timeout)
STDOUT = oProcess.StandardOutput.ReadToEnd()
STDERR = oProcess.StandardError.ReadToEnd()
Output = Output:STDOUT:@CRLF
If STDERR<>""
Output = Output:"STDERR:":STDERR:@CRLF
Endif
oProcess = 0
objInfo = 0
Return (Output)
#EndSubroutine
Return
;==========================================================
Finally, here is a real fun one... try this in your browser, then write WB code to translate the json
https://api.funtranslations.com/translate/morse.json?text=hello
I must be missing something again. It seems trivial to extract the values.
For Example,
AddExtender('ilcjs44i.dll', 0, 'ilcjs64i.dll')
Mesage = 'Faliure to launch'
Data = $"{
"success":: {
"total":: 1
},
"contents":: {
"translated":: ".... . .-.. .-.. --- ",
"text":: "hello",
"translation":: "morse"
}
}$"
if jsValid(Data)
h = jsParse(Data)
nTotal = jsValueGet(h,'success.total')
if ntotal
hCon = jsValueGet(h,'contents')
Text = jsValueGet(hCon,'text')
Lang = jsValueGet(hCon,'translation')
Translation = jsValueGet(hCon,'translated')
Mes = 'Morris code for "':text:'" is "':Translation:'"'
endif
Pause('Translation', Mes)
endif
jsConClose()
exit
Quote from: td on July 08, 2025, 02:40:54 PMI must be missing something again. It seems trivial to extract the values.
It is with the Extender [shout out]. I was thinking more of getting the json with a Rest request, then parsing w/out prior knowledge of the node names. But I think Kirby has enough to work with.
cUrl = "https://api.funtranslations.com/translate/morse.json?text=hello"
request = Createobject("WinHttp.WinHttpRequest.5.1")
request.Open("GET", cUrl, @False )
request.Send()
json = request.ResponseText
ObjectClose(request)
Message("Response",json)
;then add you json Extender parsing
So much goodness!!! thanks guys!!
-K
Quote from: kdmoyers on July 09, 2025, 09:14:04 AMSo much goodness!!! thanks guys!!
-K
You are most welcome. Below is a free/useful source to practice with, and an excellent workout for the Json Extender.
https://mixedanalytics.com/blog/list-actually-free-open-no-auth-needed-apis/