VBA How To Loop Through JSON response from WinHttp.WinHttpRequest - json

I can't figure out how to properly loop through a JSON(Object) response from the WinHttp.WinHttpRequest
that I am getting.
Below are the References being used. I prefer to just keep it as is and use WinHttpRequest
Dim response As Object ' global
Function sendRequest(requestURL As String) ' send the http REST request url of API transaction
Dim request As New WinHttp.WinHttpRequest
request.Open "GET", requestURL, True
request.setRequestHeader "Authorization", "Bearer " + tokenResp
request.setRequestHeader "Accept", "application/json"
request.send
request.waitForResponse
Set response = ParseJson(request.ResponseText)
' Debug.Print vbNewLine & "Response : " & vbNewLine
' Debug.Print "Request ResponseText : " & request.ResponseText
End Function
Below is how the JSON response I am getting looks like. There are more records.
{
"Record":[
{
"NameValue":[
{
"Name":"name1",
"Value":"value1"
},
{
"Name":"name2",
"Value":"value2"
}
]
},
{
"NameValue":[
{
"Name":"name1",
"Value":"value1"
},
{
"Name":"name2",
"Value":"value2"
}
]
}
]
}
The response is an object.
I can do Debug.Print response("Record")(1)("NameValue")(1)("Value") to get the first record
Debug.Print response("Record")(1)("NameValue")(1)("Value") ' value1
but I need to be able to loop through it to get all values and not just the first one
I can't seem to find a way to convert the JSON to an array with a array length() or size() function. I searched and found UBound() and LBound() but I think it can only be used on arrays and not Objects.
I'd appreciate any help. I do Java most of the times and things are a bit different in VBA.
Thank you.

response("record") is a Collection (also anything else in [] in your json). Each item in that collection is a Dictionary (likewise anything in {})
Dim itmRec, nameVal, itm
For each itmRec in response("Record")
set nameVal = itmRec("NameValue")
for each itm in nameVal
debug.print itm("Name"), itm("Value")
next itm
Next itmRec

Related

Excel VBA-JSON: How do loop through an array inside a JSON object?

Consider this JSON object:
{
"fileName": "Batch_01032023_SakerItemData.xlsx",
"fileLocation": "C:\\Temp",
"message": "There are 3 errors. Please correct and try again.",
"error": [
"{Item} failed validation:Item is required.:8",
"{Type} failed validation:Type is required.:8",
"{Class} failed validation:Class is required.:8"
]
}
I am using the JsonConverter from this repo https://github.com/VBA-tools/VBA-JSON
Consider this VBA code:
Dim jsonObject As Object, item As Object
Dim objHTTP As Object
Dim url As String
Dim result As String
Dim async As Boolean
Dim body As String
body = "{""fileLocation"":""{fileLocation}""}"
body = Replace(body, "{fileLocation}", Replace(fileLocation, "\", "\\"))
Set objHTTP = CreateObject("WinHttp.WinHttpRequest.5.1")
With objHTTP
.Open "POST", url, async
.SetRequestHeader "Content-Type", "application/json"
.SetRequestHeader "Accept", "application/json"
.SetRequestHeader "Authorization", "Basic " + _
Base64Encode(authUser + ":" + authPassword)
.Send body
.waitForResponse
result = .responseText
End With
Set jsonObject = ParseJson(result)
*** What is the syntax here to loop through error object? ****
For Each item In jsonObject("error")(1)
Next
this line Set jsonObject = ParseJson(result) does not throw an error and seems to work, yet when I get to the 'for each' loop, I get Error # 424 'Object Required'.
My question is this: How can I loop through the 'error' array in the 'jsonObject' so that I can display the validation errors to the user? The error array is dynamic.
The key error returns a Collection, so first assign it to a variable declared as Collection...
Dim col As VBA.Collection
Set col = jsonObject("error")
Then loop through each item in the collection...
Dim itm As Variant
For Each itm In col
Debug.Print itm
Next itm

Using Access VBA to read JSON data (part two)

The following subroutine reads Json data from an internet site:
Sub DistanceRetrieve()
Dim url As String, Response As String
Dim PointCordinate As String
Dim WinHttpReq As Object, Json As Object, Paths As Object, Item As Object, NextItem As Object,
Points As Object
Set WinHttpReq = CreateObject("MSXML2.XMLHTTP.6.0")
With WinHttpReq
url = "https://distances.dataloy.com/route/route?point=" & Latitude1 & "," & Longitude1 &
"&point=" & Latitude2 & "," & Longitude2 & "&block_sc=" & BlockSC & "&block_nw=" & BlockNW
&"&block_ne=" & BlockNE
.Open "GET", url, False
.SetRequestHeader "Content-Type", "application/json"
.SetRequestHeader "X-API-Key", "DnqL8TJbh77wn0DphKhhI6GPOy3fnKDt2fDUMB8j"
.Send
If .Status = 200 Then
Response = .ResponseText
Set Json = JsonConverter.ParseJson(Response)
Set Paths = Json("paths")
For Each Item In Paths
Distance = Item("distance")
Set Points = Item("points")
For Each NextItem In Points
PointCoordinate = NextItem("coordinates")
If PointCoordinate = SuezCanalCoordinate Then
MsgBox ("Sues Canal is on route.")
End Sub
End If
Next
MsgBox ("Sues Canal is not on route.")
End Sub
Next
End If
End With
End Sub
N.B. Some variables are declared as public.
The "For Each NextItem In Points" statement gives "Object required" error message when the code is run.
Hereinafter is the first part of the Json data:
{ "info" : { "copyrights" : [ "Viku AS"], "took" : 1346 }, "paths" : [ { "distance" : 10289.034929805617, "bbox" : [ -10.026282, 1.124421, 113.648011, 60.180576], "points" : { "coordinates" :[[4.960373,60.180576],[4.962496,60.162612],[4.986241,60.143381],[4.944009,60.137372],[4.944009,60.137372],[4.10086,59.45105],[4.100343,59.002301],[1.42238,50.973884],[1.328024,50.868336],[1.308167,50.854352],[1.16305,50.752155],[1.065639,50.683556],[0.919434,50.580593],[0.602589,50.517847],[-0.070224,50.384606],[-0.376109,50.333315],[-1.053553,50.219721],[-1.730997,50.106127],[-2.408441,49.992533],[-2.88957,49.908579],[-3.209387,49.787494],[-3.806258,49.561516],[-4.403129,49.335538],[-5.0,49.109559],[-5.51017,48.916407],[-5.861724,48.642143],[-6.169181,48.246339],[-6.476639,47.850535],[-6.784096,47.454732],[-7.091553,47.058928],[-7.39901,46.663124],[-7.706467,46.26732],[-8.013925,45.871517],[-8.321382,45.475713],[-8.628839,45.079909],[-8.936296,44.684106],[-9.243753,44.288302],[-9.55121,43.892498],[-9.858668,43.496694],[-9.891568,43.45434],[-10.023932,43.260722],[-10.026282,42.88182],[-10.026186,42.46553],[-10.026082,42.015288],[-10.025979,41.565047],[-10.025875,41.114806],[-10.025771,40.664564],[-10.025667,40.214323],[-10.025564,39.764081],[-10.02546,39.31384],[-10.025356,38.863598],[-10.025356,38.69584],[-9.998078,38.603524],[-9.908628,38.296362],[-9.78081,37.857447],[-9.652993,37.418532],[-8.509321,36.452241],[-7.973851,36.329996],[-7.438382,36.20775],[-6.902912,36.085504],[-6.367442,35.963259],[-6.200541,35.925156],[-6.100124,35.925653],[-5.749613,35.937037],[-5.608748,35.93671],[-5.551674,35.951129],[-5.508509,35.962488],[-5.469502,35.972753],[-5.427,35.983562],[-5.072639,36.028626],[-4.523336,36.098481],[-3.974033,36.168336],[-3.42473,36.238191],[-2.875427,36.308045],[-2.326124,36.3779],[-2.268051,36.385285],[-2.188115,36.395701],[-2.188115,36.395701],[6.546112,37.329032],[10.409177,37.409177],[32.220277,31.534171],[32.351432,31.366935],[32.367263,31.321183],[32.326332,31.275712],[32.310771,31.256955],[32.306485,31.250784],[32.305175,31.245859],[32.304701,31.240173],[32.304078,31.22865],[32.30432,31.220009],[32.305401,31.193798],[32.30868,31.101482],[32.30884,31.096973],[32.313349,30.959484],[32.315801,30.881891],[32.316749,30.832008],[32.317177,30.818442],[32.317669,30.81143],[32.319202,30.805119],[32.326993,30.777533],[32.335298,30.748205],[32.338183,30.736395],[32.340812,30.72563],[32.342098,30.720024],[32.343728,30.712811],[32.344013,30.705045],[32.342476,30.69789],[32.339344,30.684428],[32.33286,30.65656],[32.326093,30.627388],[32.324259,30.620015],[32.322923,30.616423],[32.315078,30.602051],[32.311989,30.596237],[32.309886,30.591612],[32.308995,30.589652],[32.304839,30.580932],[32.303776,30.570936],[32.303946,30.565621],[32.305155,30.560251],[32.309042,30.549282],[32.312801,30.544911],[32.320118,30.535669],[32.328006,30.526559],[32.33423,30.518056],[32.336188,30.513515],[32.336788,30.512121],[32.33897,30.506124],[32.343769,30.484001],[32.345429,30.476297],[32.349985,30.452174],[32.357802,30.435216],[32.362452,30.41324],[32.365013,30.401903],[32.371307,30.364477],[32.372001,30.362383],[32.372923,30.360631],[32.37432,30.358856],[32.413348,30.314052],[32.442811,30.282656],[32.4683,30.273356],[32.487274,30.267524],[32.506479,30.261663],[32.528893,30.253179],[32.538655,30.242899],[32.55205,30.223001],[32.565398,30.200991],[32.567636,30.193881],[32.568511,30.186485],[32.568866,30.174391],[32.569061,30.165197],[32.569083,30.164319],[32.571572,30.065582],[32.573102,30.053687],[32.583382,29.999835],[32.585442,29.991212],[32.586504,29.984021],[32.587067,29.978722],[32.587502,29.972775],[32.586472,29.964744],[32.58411,29.957644],[32.580461,29.950635],[32.57586,29.943603],[32.571401,29.939105],[32.567231,29.935892],[32.56278,29.931928],[32.559968,29.92972],[32.553295,29.924821],[32.550781,29.920572],[32.546005,29.90946],[32.546005,29.903795],[32.554049,29.852356],[32.553995,29.847614],[32.534316,29.773183],[32.54236,29.63257],[32.544371,29.61334],[32.548393,29.592358],[32.599674,29.480381],[32.614756,29.454118],[32.630844,29.417339],[32.740534,29.181429],[32.820887,29.008613],[32.940536,28.751286],[33.033041,28.592489],[33.181886,28.374556],[33.31458,28.18027],[33.340722,28.15811],[33.36586,28.137718],[33.60102,27.943094],[33.655442,27.898053],[33.674193,27.88355],[33.703706,27.860724],[33.761019,27.809153],[33.815465,27.752737],[33.818462,27.749631],[33.837436,27.72997],[34.074325,27.532797],[34.102887,27.509024],[34.102887,27.509024],[42.75544,14.336583],[43.189582,13.344682],[43.189582,13.344682],[43.185256,13.313807],[43.188028,13.271231],[43.19972,13.234306],[43.340825,12.677617],[43.364873,12.629906],[43.380267,12.599365],[43.469014,12.507192],[43.691211,12.418707],[43.71623,12.408744],[44.142069,12.239163],[44.567907,12.069581],[44.993746,11.9],[45.080711,11.927235],[45.520055,12.064824],[45.9594,12.202414],[46.398745,12.340004],[46.838089,12.477593],[47.277434,12.615183],[47.716778,12.752772],[48.156123,12.890362],[48.595468,13.027952],[49.034812,13.165541],[49.474157,13.303131],[49.913501,13.440721],[50.352846,13.57831],[50.792191,13.7159],[51.231535,13.853489],[51.67088,13.991079],[52.110225,14.128669],[52.549569,14.266258],[52.988914,14.403848],[58.438634,15.679702],[58.438634,15.679702],[80.701832,5.701832],[93.468048,6.26668],[93.644801,6.27979],[94.095453,6.313216],[94.546105,6.346642],[94.996757,6.380069],[95.087901,6.386743],[95.538651,6.419749],[95.6777,6.381267],[96.113066,6.26078],[96.548433,6.140293],[96.983799,6.019807],[97.419165,5.89932],[97.854532,5.778833],[97.977656,5.62999],[98.265553,5.281954],[98.553451,4.933918],[98.841348,4.585882],[99.185654,4.304885],[99.535149,4.019653],[99.738417,3.85376],[99.932689,3.69521],[100.281985,3.410141],[100.63128,3.125072],[100.784531,3.0],[101.0,2.813011],[101.196657,2.711314],[101.448781,2.580933],[101.651348,2.420594],[102.003384,2.139419],[102.028193,2.119605],[102.250359,1.920972],[102.390329,1.853969],[102.79612,1.65972],[102.802769,1.656537],[102.950924,1.561332],[103.149876,1.425921],[103.343872,1.260979],[103.376343,1.233371],[103.465236,1.19105],[103.508891,1.172935],[103.575394,1.14584],[103.616935,1.133238],[103.678364,1.124421],[103.732268,1.127876],[103.788245,1.161041],[103.829739,1.182472],[103.862881,1.19766],[103.881411,1.205894],[103.931297,1.228061],[103.992803,1.250861],[104.055691,1.259842],[104.10683,1.26537],[104.121072,1.267352],[104.161425,1.27297],[104.208418,1.278497],[104.241756,1.284231],[104.272688,1.289551],[104.327282,1.297842],[104.449603,1.40631],[104.530497,1.551922],[104.749777,1.946632],[104.969057,2.341341],[105.078485,2.538313],[105.133782,2.987055],[105.151868,3.133821],[105.387157,3.519243],[105.509613,3.719836],[105.509613,3.719836],[109.625784,12.40235],[113.648011,21.648011]] ....
N.B. Unnecessary part at the data end is truncated.

JSON posting to update Trello Custom Field from VBA

I'm using VBA in Excel with the amazing VBA-Tools by Tim Hall and I'm able to do pretty much everything trello related, create card, list, comments, etc
What's been frustating to me the last couple of days is that I cannot put a value in the custom field of a card, I tried everything I can think of
This is the code
Sub atualizaCustomField(listaNome As String, cardNome As String, idCF As String, valor As String)
Dim Client As New WebClient
Client.BaseUrl = "https://api.trello.com/1/"
Dim Request As New WebRequest
Request.ContentType = "application/json"
Request.Method = WebMethod.HttpPut
Request.Resource = "cards/{idCard}/customField/{idCustomField}/item"
Request.AddUrlSegment "idCard", pegaIDCard(listaNome, cardNome)
Request.AddUrlSegment "idCustomField", idCF
Request.AddQuerystringParam "key", ApplicationKey
Request.AddQuerystringParam "token", UserToken
Debug.Print Request.FormattedResource
Dim Response As WebResponse
'Set Response = Client.Execute(Request)
Set Response = Client.PostJson(Client.BaseUrl & Request.FormattedResource, valor)
Debug.Print valor
Debug.Print Response.StatusCode & ": " & Response.Content
End Sub
What's different about this is that you have to post a JSON and not simply make the request like everything else, must match this example (from trello developer site):
{
"value": {
"text": "<string>"
}
}
in my code the variable "valor" holds this string.
I know this was 9 months ago, but I ran into the same issue and found a solution that may be useful to others.
As the OP said, the "value" field needs to have json formatting and be placed in the request body. This is achieved by passing a Dictionary type to the .AddBodyParameter method.
Dim body as Object
Set body = New Dictionary
body.Add "text", "<string>"
Request.AddBodyParameter "value", body

how can i post json to google people.api

by creating an contact,
i always get the answer
Invalid JSON payload received. Unknown name
my strJson is
{
"names": [
{
"familyName": "NN"
}
]
}
Set web_HTTP = CreateObject("WinHttp.WinHttpRequest.5.1")
web_Url_CreateContacts = "https://people.googleapis.com/v1/people:createContact"
web_HTTP.Open "Post", web_Url_CreateContacts & "?" & _
"access_token=" & Token & "&" & _
"key=" & ApiKey & "&" & _
strJson
It looks like you're putting the strJson as part of the query string which would mean it should be urlencoded probably. But I would discourage that. It's better to post with the RequestBody parameter of winHTTP, than trying to put it all in one string. and posting.
Set xmlhttp = CreateObject("MSXML2.ServerXMLHTTP")
'list
'~~> Indicates that page that will receive the request and the type of request being
submitted
xmlhttp.Open "POST",
"https://www.example.com/api/go/XSx/rest/inquiry/resolveXInquiry", False
'~~> Indicate that the body of the request contains form data
xmlhttp.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
''or JSON content type
'~~> Send the data as name/value pairs
'["50061555", "50055854", "500615516", "500615576", "50055910"]
xmlhttp.send "request={""inquiryIds"":[50061333],""requestType"":""Report2"",""from"":""*parameter"",""comment"":""report""}"
Thanks a lot!
That was the idea I was missing!
strJSON must be sent as a body (XMLHttpRequest.send (body)).

Excel VBA macro using iTunes search API - fastest way to query & parse JSON results

I am trying to build Excel page from iTunes query data.
An example for Angry Birds app my query would look like:
https://itunes.apple.com/lookup?id=343200656&country=AL checking Albania iTunes
https://itunes.apple.com/lookup?id=343200656&country=DZ checking Algeria iTunes
... 150 more stores
My question is the most efficient way to do this query and parse response.
I only know how to to xmlhttp query. Please enlighten me as the better way to do this.
I have read some documentation for VB-JSON, Json.net, CDataSet, fastJSON, but cannot figure out how to get started trying those tools. Anyone have more VBA code examples pulling JSON or way to explain usage of these frameworks to a newb?
Dim innerHTML As Object
Dim myText As String
JsonCheck = ""
Set innerHTML = CreateObject("Microsoft.XMLHTTP")
With innerHTML
.Open "GET", iTunesAPI_link, False
.send
myText = .responsetext
End With
Set innerHTML = Nothing
If InStr(myText, ":0") = 20 Then 'no results found
result = "Down"
ElseIf InStr(myText, "Your request produced an error.") = 46 Then 'link error
result = HTMLCheck(human iTunes link)
Else 'found the app
result = call function which parses myText for desired fields
Endif
Here's a basic approach using the scriptcontrol:
Sub Tester()
Dim json As String
Dim sc As Object
Dim o
Set sc = CreateObject("scriptcontrol")
sc.Language = "JScript"
json = HttpGet("https://itunes.apple.com/lookup?id=343200656&country=AL")
'some json property names may be keywords in VBA, so replace with
' something similar....
json = Replace(json, """description""", """description_r""")
Debug.Print json
sc.Eval "var obj=(" & json & ")" 'evaluate the json response
'add some accessor functions
sc.AddCode "function getResultCount(){return obj.resultCount;}"
sc.AddCode "function getResult(i){return obj.results[i];}"
Debug.Print sc.Run("getResultCount")
Set o = sc.Run("getResult", 0)
Debug.Print o.kind, o.features, o.description_r
End Sub
Function HttpGet(url As String) As String
Dim oHTML As Object
Set oHTML = CreateObject("Microsoft.XMLHTTP")
With oHTML
.Open "GET", url, False
.send
HttpGet = .responsetext
End With
End Function
There's a worked-out approach in Codo's answer to this question: Excel VBA: Parsed JSON Object Loop
I had a similar issue with querying Salesforce's REST API and found dealing with JSON through ScriptControl ended up being unmanageable. I used the following library for parsing and converting to JSON and it's worked perfectly for me: https://code.google.com/p/vba-json/.
Dim JSON As New JSONLib
Dim Parsed As Object
Set Parsed = JSON.parse(jsonValue)
Debug.Print Parsed("resultCount")
Debug.Print Parsed("results")(0)
Using that library, I then wrapped up some of the common functionality for making web requests that I think would help you out: https://github.com/timhall/Excel-REST
Using these libraries, your code would look something like the following:
Dim iTunesClient As New RestClient
iTunesClient.BaseUrl = "https://itunes.apple.com/"
Dim Request As New RestRequest
Request.Format = json
Request.Resource = "lookup"
Request.AddQuerystringParam "id", "343200656"
Request.AddQuerystringParam "country", "AL"
Dim Response As RestResponse
Set Response = iTunesClient.Execute(Request)
' => GET https://itunes.apple.com/lookup?id=343200656&country=AL
If Response.StatusCode = 200 Then
' Response.Data contains converted JSON Dictionary/Collection
Debug.Print "Result Count: " & Response.Data("resultCount")
Dim i As Integer
For i = LBound(Response.Data("results")) To UBound(Response.Data("results"))
Debug.Print "Result " & i & ": " & Response.Data("results")(i)
Next i
Else
Debug.Print "Error: " & Response.Content
End If