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