Access nested values in JSON-Object in VBA - json

I would like to get data from a JSON-Object, that I got from a Rest-API, with VBA to display some data into an Excel-Worksheet. I'm using the library (VBA-JSON v2.3.1 JsonConverter).
I have the following JSON-Object:
{
"devices": [
{
"data": [
{
"id": 0,
"name": "Hello"
},
{
"id": 1,
"name": "How are you?"
},
{
"id": 2,
"name": "Bye"
}
],
"type": "LORA"
}
],
"includedTypes": [
"LORA"
]
}
I want to get the objects in the array from "data".
My VBA-Code is this:
Dim js1Object As Object
Dim response1 As String
strUrl = "https://XXXXXXXXXXXdevices
Set hReq = CreateObject("MSXML2.XMLHTTP")
With hReq
.Open "GET", strUrl, False
.SetRequestHeader "Authorization", "Bearer " & apitoken
.Send
response1 = hReq.responseText
MsgBox response1
Set js1Object = JsonConverter.ParseJson(response1)
j = 31
For Each item In js1Object("devices")
ws.Cells(j, 7) = item("id")
ws.Cells(j, 10) = item("name")
j = j + 1
Next
MsgBox (response1)
End With
How can I access the values from "data"?
If the JSON would look like the object below, my code would work. But my problem is, that the response that I get, is more nested and I can't directly access "data".
{
"devices": [
{
"id": 0,
"name": "Hello"
},
{
"id": 1,
"name": "How are you?"
},
{
"id": 2,
"name": "Bye"
}
]
}
I just don't know, how to access deeper values in JSON-Object. The solutions from similar questions with print are not working with my code.
Thanks for helping me!

Your "root" json object is a Dictionary - the key "devices" is a Collection object, and the first element is another dictionary with two keys "data" and "type".
"data" is another Collection of Dictionaries, so you can do this to get to the contained id and name values:
Dim Json As Object, data, d
'reading json from a worksheet cell...
Set Json = JsonConverter.ParseJson(Range("A5").Value)
Set data = Json("devices")(1)("data") 'Dictionary key->Collection index->Dictionary key
For Each d In data
Debug.Print d("id"), d("name")
Next d
Output:
0 Hello
1 How are you?
2 Bye

Related

Parse multiple JSON/VBA objects with VBA-JSON

I have the following JSON response:
[
{
"id": 1354345345,
"date": "2021-10-01T23:29:42.000000+02:00",
"count": 0,
"year": 2020,
"area": 232,
"numberList": [
8693978
],
"Property": {
"PropertyID": 135005860000118,
"PropertyNumber": 2244
}
},
{
"id": 2345235345,
"date": "2021-02-13T13:40:30.000000+01:00",
"count": 2,
"year": 2020,
"area": 122,
"numberList": [
8693978
],
"Property": {
"PropertyID": 153005860001536,
"PropertyNumber": 1555
}
}
]
Inside the array [], there can be several object {}, each with a value in "area". In this example, there are two objects in the array.
I am trying to parse the JSON via VBA-JSON.
I've tried the following VBA code, but it will only return the names of each object item and not the value.
Set Json = JsonConverter.ParseJson(responseText)
For Each Item In Json
For Each i In Item
Debug.Print i
Next
Next
VBA debug console will show:
id
date
count
year
area
numberList
Property
id
date
count
year
area
numberList
Property
How do I fetch the area of each object?
JsonConverter.ParseJson(responseText) creates an object keeping Scripting Dictionaries... So, they expose keys and items. Based on that logic, please try the next way of "area" values extracting:
The string you show misses a ":" character (replaced with ";").Here: "area"; 232,. It should be correct to be parsed...
The next code version will iterate between the object keys and items, extracted the value (item) for the key "area":
Dim json As Object, strFile As String, responseText As String, dict, i As Long
responseText = "the corrected string you show..."
Set json = JsonConverter.ParseJSON(responseText)
For Each dict In json
For i = 0 To dict.count - 1
If dict.Keys()(i) = "area" Then
Debug.Print TypeName(dict), TypeName(dict.Keys()(i)), TypeName(dict.Items()(i))
Debug.Print dict.Items()(i)
End If
Next i
Next dict

Modifying VBA JSON File

I want to modify a JSON file in excel using vba.
So I have this JSON file
{
"root": [{
"STATUS_RESPONSE": {
"STATUS": {
"STATUS": {
"OWNER": "root",
}
},
"REQ_ID": "00000",
"RESULT": [{
"USER": {
"BUSINESS_ID": "A",
"USER_NUMBER": "45",
"LANGUAGE": "F",
}
},
{
"USER_SESSION": {
"USER_ID": "0000001009",
"HELP_URL": "http://google.com",
}
},
{
"USER_ACCESS": {
"SERVICES_ROLE": "true",
"JOURNALLING": "true",
}
}]
}
}]
}
I want to modify just the "BUSINESS_ID"
Then I can export to the same JSON file using this
Private Sub CommandButton2_Click()
Dim rng As Range, items As New Collection, myitem As New Dictionary, i As Integer, cell As Variant, myfile As String
Dim FSO As New FileSystemObject
Dim buss As String
Dim JsonTS As TextStream
Set rng = Range("A2")
Set JsonTS = FSO.OpenTextFile("test.json", ForReading)
JsonText = JsonTS.ReadAll
JsonTS.Close
Set JSON = ParseJson(JsonText)
JSON("root")(1)("STATUS_RESPONSE")("RESULT")(1)("USER")("BUSINESS_ID") = Sheets(1).Cells(2, 1).Value
buss = JSON("root")(1)("STATUS_RESPONSE")("RESULT")(1)("USER")("BUSINESS_ID")
myfile = "test.json"
Open myfile For Output As #1
Write #1, buss
Close #1
End Sub
I can edit the cell and this would replace the JSON file but it takes away the whole structure from the JSON file above.
I get something similar to this like in the json file if I change the business id to C:
"C"
Is there a way that I can just modify the thing I need in the existing file without everything else disappearing
You should be exporting the whole JSON object, not just one part of it.
Write #1, JsonConverter.ConvertToJson(JSON, Whitespace:=2)

VBA: count items in JSON response string / trello get Cards count in a List

I'm using VBA-web (https://vba-tools.github.io/VBA-Web/) to access trello api, to get cards in a list
My function looks like that:
Public Function CountCardsinList(ListId As String) As Integer
WebHelpers.EnableLogging = False
Dim TrelloClient As New WebClient
TrelloClient.BaseUrl = "https://api.trello.com/1/"
Dim Request As New WebRequest
Request.Format = WebFormat.Json
Request.ResponseFormat = Json
Request.Resource = "lists/{ListId}/cards"
Request.AddUrlSegment "ListId", ListId
Request.AddQuerystringParam "key", TrelloAPIKey
Request.AddQuerystringParam "token", TrelloAPIToken
Request.AddQuerystringParam "filter", "open"
Dim Response As WebResponse
Set Response = TrelloClient.Execute(Request)
If Response.StatusCode = WebStatusCode.Ok Then
Debug.Print Response.Content '
'Response.Data("idList").Count
Debug.Print "CountCardsinList =>>> " & Response.Content
CountCardsinList = Response.Data("idList").Count
Else
MsgBox Response.StatusDescription, vbCritical, "Error " & Response.StatusCode
CountCardsinList = ""
End If
Debug.Print "CountCardsinList =>>> " & Response.Content
'Set CountCardsinList = Request
End Function
I receive correct JSON reply from the api:
[{
"id": "584e798dd570ae187b293e5b",
"checkItemStates": null,
"closed": false,
"dateLastActivity": "2016-12-30T09:24:57.531Z",
"desc": "",
"descData": null,
"idBoard": "57873ba94794058756fa0a96",
"idList": "57873bb3a725f734089702b2",
"idMembersVoted": [],
"idShort": 90,
"idAttachmentCover": null,
"manualCoverAttachment": false,
"idLabels": ["57873ba984e677fd3683bef8"],
"name": "card name / other stuff",
"pos": 1999.9923706054688,
"shortLink": "izoqvWJk",
"badges": {
"votes": 0,
"viewingMemberVoted": false,
"subscribed": false,
"fogbugz": "",
"checkItems": 0,
"checkItemsChecked": 0,
"comments": 0,
"attachments": 0,
"description": false,
"due": "2016-12-26T11:00:00.000Z",
"dueComplete": false
},
"dueComplete": false,
"due": "2016-12-26T11:00:00.000Z",
"idChecklists": [],
"idMembers": ["54f0cc079bf18f2798dda8bd"],
"labels": [{
"id": "57873ba984e677fd3683bef8",
"idBoard": "57873ba94794058756fa0a96",
"name": "Urgent",
"color": "red",
"uses": 14
}],
"shortUrl": "https://trello.com/c/vfvfdvdfv",
"subscribed": false,
"url": "https://trello.com/c/fdvfdvdfv/cfvdfv"
},
{
"id": "5832c2fa7f55fe5637d972ea",
"checkItemStates": null,
"closed": false,
"dateLastActivity": "2016-12-30T09:25:09.222Z",
"desc": "",
"descData": null,
"idBoard": "57873ba94794058756fa0a96",
"idList": "57873bb3a725f734089702b2",
"idMembersVoted": [],
"idShort": 80,
"idAttachmentCover": null,
"manualCoverAttachment": false,
"idLabels": ["57873ba984e677fd3683bef6"],
"name": "other card name",
"pos": 2023.9922790527344,
"shortLink": "XhUPgcsD",
"badges": {
"votes": 0,
"viewingMemberVoted": false,
"subscribed": false,
"fogbugz": "",
"checkItems": 0,
"checkItemsChecked": 0,
"comments": 0,
"attachments": 0,
"description": false,
"due": "2016-12-30T15:00:00.000Z",
"dueComplete": false
},
"dueComplete": false,
"due": "2016-12-30T15:00:00.000Z",
"idChecklists": [],
"idMembers": ["54fdbe1a8ecdf184596c7c07"],
"labels": [{
"id": "57873ba984e677fd3683bef6",
"idBoard": "57873ba94794058756fa0a96",
"name": "Medium",
"color": "yellow",
"uses": 1
}],
"shortUrl": "https://trello.com/c/XhdfvdfvUPgcsD",
"subscribed": false,
"url": "https://trello.com/c/XhUPgcsfdvdffvD/
"
But I cannot correctly count idList -> and I'm trying to get number of cards in a list, by using Response.Data("idList").Count
Any information how to do it proper way? or which is the best way to parse JSON data?
General:
Your JSON isn't properly closed. I added }] to the end to close and placed in cell A1 of activesheet (as I don't have the API info). I then read that in from the cell as if it were response text.
Process:
I then used JSONConverter to parse this string from the sheet. This requires you to also add a reference to Microsoft Scripting Runtime via VBE > Tools > References.
The returned object is a collection of dictionaries. I test each dictionary for the existence of an idList key and if present add 1 to the variable itemCount, which keeps track of how many idLists there are.
Code:
Public Sub GetInfoFromSheet()
Dim jsonStr As String, item As Object, json As Object, itemCount As Long
jsonStr = [A1]
Set json = JsonConverter.ParseJson(jsonStr)
For Each item In json 'collection
If item.Exists("idList") Then itemCount = itemCount + 1
Next item
Debug.Print "idList count: " & itemCount
End Sub

Iterating through nested objects with VBJSON

I am attempting to connect to the SmartSheet API through VBA to pull the contents into an Excel sheet. I found the VBJSON library which has helped me a bit but I am struggling with iterating through the objects and pulling specific values.
I want to access the contents of the "Value" attribute for each row then do the same for subsequent rows. My biggest problem is that I do not know how this VBJSON library works since I cannot find any documentation on it and there are only a few examples and they deal with relatively straightforward JSON examples.
Desired Output
Row 1 Column 1 Content | Row 1 Column 2 Content
Row 2 Column 1 Content | Row 2 Column 2 Content
JSON
{
"id": 1,
"name": "Sheet Name",
"columns": [
{
"id": 1,
"index": 0,
"title": "Title of Column",
"type": "TEXT_NUMBER",
"primary": true
},
{
"id": 2,
"index": 1,
"title": "Title of Second Column",
"type": "TEXT_NUMBER"
},
],
"rows": [
{
"id": 1,
"rowNumber": 1,
"cells": [
{
"type": "TEXT_NUMBER",
"value": "Row 1 Column 1 Content",
"columnId": 1,
},
{
"type": "TEXT_NUMBER",
"value": "Row 1 Column 2 Content",
"columnId": 2,
},
],
"locked": true,
"lockedForUser": true,
"expanded": true,
"createdAt": "2013-10-11T13:43:24-05:00",
"modifiedAt": "2013-11-12T15:13:54-06:00"
},
{
"id": 2276445193037700,
"rowNumber": 2,
"cells": [
{
"type": "TEXT_NUMBER",
"value": "row 2 column 1 content",
"columnId": 1,
},
{
"type": "TEXT_NUMBER",
"value": "row 2 column 2 content",
"columnId": 2,
}
]
}
VBJSON library
http://www.ediy.co.nz/vbjson-json-parser-library-in-vb6-xidc55680.html
Below is code I've pieced together from what I could find online and right now it pulls the values associated with each attribute in the row. But I only need to pull the contents of the "Value" portion and I can't seem to figure out how to do that. I think I really just need help with my for loop because I have the JSON, I have a library that appears to work, I am just struggling to figure out how to combine it all.
Dim xmlHttp As Object
Set xmlHttp = CreateObject("MSXML2.ServerXMLHTTP.6.0")
xmlHttp.Open "GET", URl, False
xmlHttp.setRequestHeader "Content-Type", "text/xml"
xmlHttp.send
Dim strDiv As String, startVal As Long, endVal As Long
strDiv = xmlHttp.ResponseText
startVal = InStr(1, strDiv, "rows", vbTextCompare)
endVal = InStr(startVal, strDiv, "]", vbTextCompare)
strDiv = "{" & Mid(strDiv, startVal - 1, (endVal - startVal) + 2) & "}"
Dim JSON As New JSON
Dim p As Object
Set p = JSON.parse(strDiv)
i = 1
For Each Item In p("rows")(1)("cells")(1)
Cells(2, i) = p("rows")(1)("cells")(1)(Item)
i = i + 1
Next
Ran into a similar problem, see my answer here: https://stackoverflow.com/a/16825736/1240745
This library has been a life-saver for me: https://github.com/VBA-tools/VBA-JSON (previously https://code.google.com/p/vba-json/)
I use it in a library I wrote for accessing Salesforce, Trello, and a few others. (Shameless plug): https://github.com/VBA-tools/VBA-Web
Using the VBA-JSON library, it would involve something like the following:
Dim Parsed As Dictionary
Set Parsed = JsonConverter.ParseJson(xmlHttp.ResponseText)
' Object -> Dictionary, so Row and Cell: Dictionary
Dim Row As Dictionary
Dim Cell As Dictionary
' Array -> Collection, so Parsed("rows"): Collection
For Each Row In Parsed("rows")
For Each Cell In Row("cells")
' Access Dictionary items by key
Cells(Row("rowNumber"), Cell("columnId")) = Cell("value")
Next Cell
Next Row
(or something similar)

Parsing JSon in Classic ASP with ASP Xtreme Evolution

I'm working on an classic ASP-project and I use ASP Xtreme Evolution to parse JSon data (found here: http://zend.lojcomm.com.br/entries/classic-asp-json-revisited/)
Anyway... I'm getting most of the JSon-data correctly but now I'm stuck on an Array.
The JSon looks like this:
{
"Product": {
"ID": "6666",
"Name": "Tha name",
"ArticleGroup": [
{
"#handleas": "array",
"Title": "Title 1",
"Article": {
"ID": "777",
"Label": "Label 1",
}
},
{
"#handleas": "array",
"Title": "Title 2",
"Article": {
"ID": "888",
"Label": "Label 2",
}
}
]
}
}
}
And the ASP look like this:
set xmlHTTP = server.createobject("MSXML2.ServerXMLHTTP.6.0")
xmlHTTP.open "GET", "http://source.of.json", false
xmlHTTP.send()
ProductFeed = xmlHTTP.ResponseText
dim ProductInfo : set ProductInfo = JSON.parse(join(array(ProductFeed)))
dim key : for each key in ProductInfo.Product.keys()
Response.Write ProductInfo.Product.ID ' Prints 6666
Response.Write ProductInfo.Product.Name ' Prints Tha Name
Next
set ProductInfo = nothing
My problem is that I cannot figure out how to access the information in ArticleGroup. All I get is [object Object],[object Object] or an empty value.
Anyone have any ideas?
Thanx!
Try the following (based on the given JSON):
Dim ArticleGroup
dim key : For Each key in ProductInfo.Product.keys()
Response.Write ProductInfo.Product.ID ' Prints 6666
Response.Write ProductInfo.Product.Name ' Prints Tha Name
For Each ArticleGroup In ProductInfo.Product.Get("ArticleGroup") '' iterate all ArticleGroup entries
Response.write ArticleGroup.Get("Title") '' get the correct key value
Next
Next
You need to iterate all ArticleGroup entries and get the value through .get(keyName). Otherwise it will return the JScript function body instead.