Access response in Json - arrays

I am using the JSON VBA library to parse a large JSON response but I can not access the elements of the response as expected.
For example the response has the structure:
{employees: [{employeeId: {id: 1234}, personNumber: "ABC123", shortName: "Bob",...},...],...}
I have tried :
Dim JsonPayload As Object
Set JsonPayload = JsonConverter.ParseJson(req.ResponseText)
MsgBox JsonPayload("dict_pDictionary")
MsgBox JsonPayload("employees")(1)("employeeId")
And also :
Set emp = JsonPayload("employees")
For Each e In emp
Debug.Print "employee", e.shortName
Debug.Print "shortName", e
Debug.Print "shortName", e.dict_pDictionary
Next e
The error is Object Does not support this property or method.
I would like to know how to loop over the response. Some are variant/object/dictionary and other parts seem to be variant/object/collection

VBA JSON converts objects ({}) to Dictionaries, and Arrays ([]) to Collections.
In your code e is a Dictionary object, not an object with named properties, so:
Dim jso As Object, emps, e
Set jso = JsonConverter.ParseJson( _
"{""employees"":[{""employeeId"": {""id"": 1234}, ""personNumber"": ""ABC123"", ""shortName"": ""Bob""}]}")
Set emps = jso("employees")
For Each e In emps
Debug.Print e("employeeId")("id") '>> 1234
Debug.Print e("shortName") '>> Bob
Next e

Related

Array as a class property

I need to pass an array as a property of a custom class, but cannot find a way to do it, and didn't find a question already answered that worked for me. So here I am.
My 'movie' class has 4 properties as you can see below: titre, annee, duree and genres. The first 3 are working well, but I'am blocked on the last one. From a string, separated by commas, I need to create an array of the different genres of the movie (ie: adventure, action, etc). I can easily create this array, but cannot find a way to assign it as a movie.property.
The code below returns an incompatibility error. I probably have to implement a let property but don't understand how to do it... Does anyone has a clue of what I am doing wrong ? Tell me if you need a bigger sample of the code.
Public Sub initialiser(ByVal strLigne As String)
Dim arrData
arrData = Split(strLigne, vbTab)
strtitre = arrData(0)
strAnnee = arrData(1)
intDuree = ConvertToInt(arrData(2))
genres = CreerTabGenre(arrData(3))
End Sub
Property Get genre() As eGenre ' eGenre is an enum, and I have no choice about that (homework...)
genre = genres() 'Here I tried all the combinations between parenthesis on both, on none, etc
End Property
edit: Maybe the problem is how I access the property after ? tabFilms is an array of all the different movies. As a test, I try to access the first genre of the array, but I'm met with 'incorrect affectation of property' error...
Function genrePopulaire(tabFilms() As film) As String
Dim i As Integer, j As Integer
For i = 0 To UBound(tabFilms)
MsgBox tabFilms(i).genre(0)
Next i
End Function
First of all, your split array uses vbTab to split the string. And you said that they are separeted by commas. If so, you should add a comma at the end of the string. It would look like:
Lord of the Rings; 2002; 200; SciFi;
and use the split array like this:
arrData = split(strLigne, ";")
Also, I've tried this code working with class module.
Try this, on the module procedure:
Sub Test()
Dim Movie As Object
Set Movie = New clsMovie
Dim arrData
'strligne example
Dim strligne As String
strligne = "TLOTR" & vbTab & "2002" & vbTab & 200 & vbTab & "SciFi"
arrData = Split(strligne, vbTab)
With Movie
.TestMovie arrData
'OUTPUT EXAMPLE:
Debug.Print "Movie's name is " & .Titre & ". La duree est " & .Duree & " minutes and it was realised on " & .Annee & " and its genre is " & .Genre
End With
'you can change value at any time
movie.titre = "Harry Potter"
debug.print movie.titre & " " & movie.duree
End Sub
On the class Module (IMPORTANT: called clsMovie):
Option Explicit
'Declare all variables as private. If you want, instead of "Private" you can do it "Public" but it can be quite dangerous on a huge project. As you are declaring them Private, it's necessary to work with Let / Get statements below.
Private pTitre As String, pAnnee As String, pDuree As String, pGenres As String
Function TestMovie(arr)
Titre = arr(0)
Annee = arr(1)
Duree = arr(2)
Genres = arr(3)
End Function
'From here to the end are the "Let / Get" properties as we work with private variables in the class
Property Get Titre() As String
Titre = pTitre
End Property
Private Property Let Titre(value As String)
pTitre = value
End Property
Property Get Annee() As String
Annee = pAnnee
End Property
Property Let Annee(value As String)
pAnnee = value
End Property
Property Get Duree() As String
Duree = pDuree
End Property
Property Let Duree(value As String)
pDuree = value
End Property
Property Get Genres() As String
Genres = pGenres
End Property
Property Let Genres(value As String)
pGenres = value
End Property

Get data from json array with in array?

I have a json like with this format
[{"ts_id": "96643010","rows": "64","columns":"Timestamp,Value", "data": [["2021-09-01T11:00:00.000+07:00",206.95],["2021-09-01T12:00:00.000+07:00",206.96],["2021-09-01T13:00:00.000+07:00",206.97],["2021-09-01T14:00:00.000+07:00",206.95],["2021-09-01T15:00:00.000+07:00",206.92],["2021-09-01T16:00:00.000+07:00",206.89],["2021-09-01T17:00:00.000+07:00",206.86],["2021-09-01T18:00:00.000+07:00",206.83],["2021-09-01T19:00:00.000+07:00",206.80],["2021-09-01T20:00:00.000+07:00",206.77],["2021-09-01T21:00:00.000+07:00",206.74],["2021-09-01T22:00:00.000+07:00",206.71],["2021-09-01T23:00:00.000+07:00",206.68],["2021-09-02T00:00:00.000+07:00",206.65],["2021-09-02T01:00:00.000+07:00",206.63],["2021-09-02T02:00:00.000+07:00",206.65],["2021-09-02T03:00:00.000+07:00",206.67],["2021-09-02T04:00:00.000+07:00",206.69],["2021-09-02T05:00:00.000+07:00",206.71],["2021-09-02T06:00:00.000+07:00",206.73],["2021-09-02T07:00:00.000+07:00",206.75],["2021-09-02T08:00:00.000+07:00",206.76],["2021-09-02T09:00:00.000+07:00",206.77],["2021-09-02T10:00:00.000+07:00",206.78],["2021-09-02T11:00:00.000+07:00",206.79],["2021-09-02T12:00:00.000+07:00",206.80],["2021-09-02T13:00:00.000+07:00",206.81],["2021-09-02T14:00:00.000+07:00",206.82],["2021-09-02T15:00:00.000+07:00",206.83],["2021-09-02T16:00:00.000+07:00",206.83],["2021-09-02T17:00:00.000+07:00",206.83],["2021-09-02T18:00:00.000+07:00",206.83],["2021-09-02T19:00:00.000+07:00",206.83],["2021-09-02T20:00:00.000+07:00",206.83],["2021-09-02T21:00:00.000+07:00",206.84],["2021-09-02T22:00:00.000+07:00",206.85],["2021-09-02T23:00:00.000+07:00",206.86],["2021-09-03T00:00:00.000+07:00",206.87],["2021-09-03T01:00:00.000+07:00",206.89],["2021-09-03T02:00:00.000+07:00",206.91],["2021-09-03T03:00:00.000+07:00",206.93],["2021-09-03T04:00:00.000+07:00",206.95],["2021-09-03T05:00:00.000+07:00",206.96],["2021-09-03T06:00:00.000+07:00",206.97],["2021-09-03T07:00:00.000+07:00",206.98],["2021-09-03T08:00:00.000+07:00",207.00],["2021-09-03T09:00:00.000+07:00",207.02],["2021-09-03T10:00:00.000+07:00",207.04],["2021-09-03T11:00:00.000+07:00",207.06],["2021-09-03T12:00:00.000+07:00",207.08],["2021-09-03T13:00:00.000+07:00",207.11],["2021-09-03T14:00:00.000+07:00",207.14],["2021-09-03T15:00:00.000+07:00",207.17],["2021-09-03T16:00:00.000+07:00",207.18],["2021-09-03T17:00:00.000+07:00",207.19],["2021-09-03T18:00:00.000+07:00",207.20],["2021-09-03T19:00:00.000+07:00",207.20],["2021-09-03T20:00:00.000+07:00",207.20],["2021-09-03T21:00:00.000+07:00",207.20],["2021-09-03T22:00:00.000+07:00",207.19],["2021-09-03T23:00:00.000+07:00",207.18],["2021-09-04T00:00:00.000+07:00",207.17],["2021-09-04T01:00:00.000+07:00",207.18],["2021-09-04T07:00:00.000+07:00",207.30]]}]
Blockquote
I have tried to get this data with VBA but unsuccess, somebody can help me with VBA code to get data from "data".
This the code i have used:
Public Sub exceljson()
Dim http As Object, JSON As Object, i As Integer
Set http = CreateObject("MSXML2.XMLHTTP")
http.Open "GET", "https://cdh.vnmha.gov.vn/KiWIS/KiWIS?service=kisters&type=queryServices&request=getTimeseriesValues&datasource=0&format=dajson&ts_id=96643010&period=P3D", False
http.Send
Set JSON = ParseJson(http.responseText)
i = 2
For Each Item In JSON
Sheets(1).Cells(i, 1).Value = Item("data")
i = i + 1
Next
MsgBox ("complete")
End Sub

Display data from dimensional JSON array in VBA, getting "Run-time error '13': Type mismatch" an error message

I'm new to StackOverflow, and I'm struggling with displaying data from a dimensional JSON array in VBA (Excel). Could you please help?
Below are the codes I'm using for displaying the data of "ShippingMethod" from the JSON.
Example of JSON:
As you are able to see the "Data" is the first object.
"Shipments" and "DisplayItems" are the array of "Data".
Also, there are multiple objects inside the "Shipments" array.
For example "ShippingMethod" and "ShippingName", and my goal is to display the data of these objects. ("LC") and ("No Charge - Lowest Cost 3-5 Day Delivery")
Here are my codes:
First method:
Dim Json1 As Dictionary
Set Json1 = JsonConverter.ParseJson(strResponse3)
home.Activate
home.Cells(x, 2) = Json1("Data")("Shipments")(1)("ShippingMethod")
Second method:
Dim Json1 As Dictionary
Set Json1 = JsonConverter.ParseJson(strResponse3)
home.Activate
x = 42
For Each Item In Json1("Data")("Shipments")
home.Cells(x, 2) = Item("ShippingMethod")
x = x + 1
Next
I'm not able to display the data of these "ShippingMethod" and "ShippingName" objects as I'm getting an error message "Run-time error '13': Type mismatch" from the VBA.
NOTE: I'm using the same method on another JSON XML, it's able to retrieve the data from the dimensional JSON array without any issues.
Update on my codes(7/8)
Dim Json1 As Dictionary, x As Long, y As Long
Dim shipments
home.Activate
x = 42
Set Json1 = JsonConverter.ParseJson(strResponse3)
Set shipments = Json1("Data")("Shipments") '<-- Getting error "Run-time error '13': Type mismatch"'
For y = 3 To shipments.count
home.Cells(x, 2) = shipments(y)("ShippingMethod")
x = x + 1
Next
Error message_screenshot for Set shipments = Json1("Data")("Shipments")
The VBA highlight this line of code after selecting "Debug" button.
Note: try the below debug.print. However, the data returned as "0".
Debug.Print VarType(Json1("Data")("Shipments"))
Update on my codes(7/21)
Dim Json1 As Dictionary, x As Long, y As Long
Dim FSO, ts, s As String
Dim shipments
home.Activate
' write json to file
Set FSO = CreateObject("Scripting.FileSystemObject")
s = ThisWorkbook.Path & "\strResponse3.json"
Set ts = FSO.CreateTextFile(s)
ts.Write strResponse3
ts.Close
MsgBox Len(strResponse3) & " bytes written to " & s
x = 42
Set Json1 = JsonConverter.ParseJson(strResponse3)
Debug.Print "Json1", VarType(Json1)
Debug.Print "Json1(Data)", VarType(Json1("Data"))
Debug.Print "Json1(Data)(PriceSummary)", VarType(Json1("Data")("PriceSummary"))
Debug.Print "Json1(Data)(Shipments)", VarType(Json1("Data")("Shipments"))
Debug.Print "Json1(Data)(DisplayItems)", VarType(Json1("Data")("DisplayItems"))
home.Cells(x, 1) = Json1("Data")("Orders")("ShipmentId")
Set shipments = Json1("Data")("Shipments")
'home.Activate
For i = 1 To shipments.count
Cells(x, 2) = shipments(i)("ShippingMethod")
x = x + 1
Next
In the Txt output file, I noticed it only returning the data of "Data":{"PriceSummary":{,. Please see the beginning of the data TXT OUTPUT screenshot and compare it with the JSON screenshot.
Also, please check the ending of the data TXT OUTPUTand compare it with the JSON screenshot. The data only contain whenever inside the "PurchaseSummary" and there is no data with the arrays "Shipment" and "DisplayItems".
Here's the Debug.Print screenshot. No data returns for Shipments and DisplayItems.
I strongly believe there is something wrong with the JSON. (Kindly please refer back to the very first screenshot for the JSON pattern)
Debug.Print result:
Json1 9
Json1(Data) 9
Json1(Data)(PriceSummary) 9
Json1(Data)(Shipments) 0
Json1(Data)(DisplayItems) 0
Update - added JSON file export and test data.
Option Explicit
Sub test()
Dim Json1 As Dictionary, x As Long, i As Long
Dim shipments
Dim FSO, ts, strResponse3 As String, s As String
strResponse3 = "{""Data"" : {" & _
"""Shipments"":[" & _
"{""ShippingMethod"":""LC""}," & _
"{""ShippingMethod"":""LC""}," & _
"{""ShippingMethod"":""LC""}" & _
"]}}"
' write json to file
Set FSO = CreateObject("Scripting.FileSystemObject")
s = ThisWorkbook.Path & "\strResponse3.json"
Set ts = FSO.CreateTextFile(s)
ts.Write strResponse3
ts.Close
MsgBox Len(strResponse3) & " bytes written to " & s
Set Json1 = JsonConverter.ParseJson(strResponse3)
Debug.Print "Json1", VarType(Json1)
Debug.Print "Json1(Data)", VarType(Json1("Data"))
Debug.Print "Json1(Data)(Shipments)", VarType(Json1("Data")("Shipments"))
Set shipments = Json1("Data")("Shipments")
'home.Activate
x = 42
For i = 1 To shipments.Count
Cells(x, 2) = shipments(i)("ShippingMethod")
x = x + 1
Next
End Sub

Nested JSON VBA (records and fields)

I have this JSON file but I can't figure out if it's nested or what, if yes should I use collections? My goal is to parse this to an Excel sheet with VBA. So far I've been only able to parse the names. Any useful links for this type of data? I only found normal JSON but nothing like this. I'm new to JSON but have to do it during my internship.
Sample JSON:
{"records":[{"id":"rec1B74TQVtWwU6cW","fields":{"Name":"compriband","Materiaux":["recPqxRrg3tFC5o6T"]},"createdTime":"2021-03-07T18:22:47.000Z"},{"id":"rec3ZdAlSQhXCVG4c","fields":{"Name":"velux","Materiaux":["recig1Rh8WFpqe0wD","recAha2bQ5BTNED9V","recWAj3FZRsPj65Gz","recfv8V2t0Pje2Llg"]},"createdTime":"2021-03-07T18:27:27.000Z"}
My code attempt:
Private Sub CommandButton1_Click()
Dim W As Worksheet
Set W = ActiveSheet
'Read column names from row 1. Should match Airtable column names. No empty columns.
Dim fields As String
colCount = 2
Do Until IsEmpty(W.Cells(2, colCount))
fields = fields & "&fields[]=" & W.Cells(2, colCount).Value
colCount = colCount + 1
Loop
'Get the data from airtable
Dim http As New WinHttpRequest
Dim resp As String
Dim url As String
url = "https://api.airtable.com/v0/appY6Wo3AmLHqHkjr/categorie?api_key=key_here" & fields
http.Open "GET", url, False
http.Send
Debug.Print "Resultats " + CStr(http.ResponseText)
Dim json As Object
Set json = JsonConverter.ParseJson(http.ResponseText)
respRecord = 1
On Error GoTo Exit_Loop
Do Until json("records")(respRecord)("fields")(W.Cells(1, 1).Value) = ""
For respCol = 1 To colCount - 1
cellValue = json("records")(respRecord)("fields")(W.Cells(1, respCol).Value)
W.Cells(respRecord + 1, respCol).Value = cellValue
Next
respRecord = respRecord + 1
Loop
Exit_Loop:
End Sub
As I said in the comments you haven't done bad so far. You are missing however some degree of understanding in how the JSON is structured.
A tool like this might help you understand the structure.
Also, I see that you have used the VBA JSON parser . The examples in the documentation should help you gain a better understanding of how to parse a JSON string.
Having said that, I will point out some stuff that should help you:
Your JSON looks like so:
Basically you have an array called records, designated by [] consisting of two items 0 and 1. These 2 items are nested JSONs. So your initial JSON is an array of JSONs.
To explicitly access the individual items of the array you can do this:
json("records")(1)
json("records")(2)
...
json("records")(n)
Now, each item consists of elements of its own. These elements could be arrays, nested jsons etc. Your items consist of two parameters id and createdTime and a nested JSON fields.
To go furhter into each item you can use this syntax:
json("records")(1)("nameOfParameter")
or
json("records")(1)("nameOfNestedJSON")
So if you wanted the 1st items id you would do:
Debug.Print json("records")(1)("id")
To loop through all the items of the array you can do this:
Dim item As Object
For Each item In json("records")
Debug.Print item("id")
Next item
The nested JSON fields consists of two parameters Name and createdTime and an array Materiaux.
You can get the parameters like so:
Debug.Print json("records")(1)("fields")("Name")
And of course you can also do:
Dim item As Object
For Each item In json("records")
Debug.Print item("fields")("Name")
Next item
You can go even deeper to access the elements of the Materiaux array:
Debug.Print json("records")(2)("fields")("Materiaux")(1)
And even loop through them:
Dim arrayItem As Variant
For Each arrayItem In json("records")(2)("fields")("Materiaux")
Debug.Print arrayItem
Next arrayItem

Access Values In Nested Array in JSON response

I have a multidimensional JSON array returned via a web request (http://www.coincap.io/history/365day/BTC). I want to cycle through the 2nd entry and retrieve its nested values.
If this was a normal array, I'd use:
For Each item In response
logic, logic, logic
currentRow = currentRow + 1
Next
This web request returns a JSON-response with 3 entries: market_cap, price, and volume. I just want to cycle through response(1) and get the price values. Each entry in price contains two keys, 0 and 1.
I would imagine that I could accomplish this by doing
For Each item in response(1)
Cells(currentRow, 1).Value = item(0)
Cells(currentRow, 2).Value = item(1)
currentRow = currentRow + 1
Next
I've also considered For Each item in response("price"). Neither works.
Sub Tester()
Dim json As String
Dim sc As Object
Dim o, n, i, p
Set sc = CreateObject("scriptcontrol")
sc.Language = "JScript"
json = HttpGet("http://www.coincap.io/history/365day/BTC")
sc.Eval "var obj=(" & json & ")" 'evaluate the json response
'add a couple of accessor functions
sc.AddCode "function numPrices(){return obj.price.length;}"
sc.AddCode "function getPrice(i){return obj.price[i];}"
n = sc.Run("numPrices")
For i = 0 To n - 1
p = Split(sc.Run("getPrice", i), ",")
Debug.Print i, p(0), p(1)
Next i
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

Resources