VBA-JSON: Add entry to Existing File - json

I'm using excel to modify existing JSON with the VBA-JSON library and I'm effectively trying to do what .push from javascript does, adding another entry to the nested array.
There's this previously posted question which illustrates what I'm trying to do but in the scope of creating a JSON file.
VBA-JSON Create nested objects
The accepted answer while helpful, doesn't show me how to add to what I already have without rebuilding it entirely. I can picture a mess of loops to parse my existing file into strings, then do something similar to what is in the post. I'm curious if there's another way to do it.
'download json
Set json = JsonConverter.ParseJson(H.responseText)
Debug.print json(1)("entries")(1)("Date")
'2019-09-25
json(1)("entries")(2)("Date") = "2019-09-26"
'error 9 Subscript out of Range
'upload json
[
{
"Entries": [
{
"Date": 2019-09-25,
"a": 1,
"b": 2
}
]
}
]
I'm able to access and modify existing entries but not add to it. I'm guessing this is because the library parses it as a defined array rather than variable? Any ideas on a simple solution or will I have to deconstruct my file into dictionaries/collections and rebuild it first?

VBA Json is really just a cheap (and effective) converter/deconverter of a json string into a nested set of dictionaries and collections. So you don't have to "deconstruct [your] file into dictionaries/collections and rebuild it" since... it already is. This is why it's necessary to add in the Microsoft Scripting Runtime library to use it.
The struggle you are dealing with is that you are treating every object in your json object as a dictionary. Instead you want to add(pop) to the entries collection. A good way to keep these separate is that in VBA JSON (as far as I've seen) if an object is a key/value pair, then it's a Dictionary and if it's just an object without a key then it's a Collection. I'm certain there is more nuance there, but it works well in this scenario.
Consider:
Sub test()
Dim Json As Object
Set Json = JsonConverter.ParseJson("[{""Entries"":[{""Date"": 2019-09-25,""a"": 1,""b"": 2}]}]")
Dim entry1 As Object
Set entry1 = Json(1)("Entries")
Stop '<--inspect Locals and see that we have a Collection here
'Add to the collection (different then adding to a dictionary)
'We will add a dictionary to the collection though
Json(1)("Entries").Add New Dictionary
'Now add to the dictionary.
Json(1)("Entries")(2).Add "Date", "2019-09-26"
Stop
Debug.Print JsonConverter.ConvertToJson(Json)
'Alternatively you could create the dictionary and add your keys, then `pop` your entries
Dim Entry As Dictionary
Set Entry = New Dictionary
Entry.Add "Date", "2019-09-26"
Entry.Add "a", "2"
Entry.Add "b", "3"
Json(1)("Entries").Add Entry
Debug.Print JsonConverter.ConvertToJson(Json)
End Sub
This should spit out what you are after (I think):
[{"Entries":[{"Date":"2019-09-25","a":1,"b":2},{"Date":"2019-09-26"}]}]
I guess another way to think through this is that if we want to add a new array to our Entries then we have to add a new Dictionary object to the Entries collection. Then we can add into the dictionary our key/value pairs like Date, a, and b.

Related

Iterate through multiple json strings to return all possible data points - VB.NET

I have a series of files that contain json strings. I can open up and loop through each file but I'm struggling to loop through each layer of the json to determine ALL possible data points within the files. The data is dynamic so some will contain certain fields / data, some won't. Without manually searching I'm struggling to capture all fields that may exists.
Key = meta
Key = meta data_version
Key = meta created
Key = meta revision
I tried a series of nested loops to iterate through level 1, then level 2 with in level 1 etc, and that gets me the format above where we have meta at level 1 and the following fields in level 2 below that.
The code falls over when the next level is an array.
Dim O2 = (o1(entry1.Key)).ToString
Dim o2j As JObject = JObject.Parse(O2)
Line 2 falls over with the following error.
Error reading JObject from JsonReader. Current JsonReader item is not
an object: StartArray. Path '', line 1, position 1.
I've searched pretty much everywhere, but most examples seem to use a static data format. So can anyone point me to an example somewhere that would suit my needs, or kindly explain how I account for the possibility of an array in the structure.
thanks in advance.

How to get data from JSON nested arrays in excel vba-json

I'm preparing some kind of software working with Excel with an API, and I'm using vba-json library, and I dont know how to get data from nested arrays on JSON.
I've tryied some tutorials and another similar questions that I fond here. But every time I try I get a different error. Runtime error 5, 9, 13. Tryied different ways to accés the data but everytime I get error when I get into an array.
Set MyRequest = CreateObject("WinHttp.WinHttpRequest.5.1")
MyRequest.Open "GET", "https://pokeapi.co/api/v2/pokemon/ditto/?fbclid=IwAR2pJwAgODOlI-Gdn8pH-RDFCcUfQWiYLZIVCnP8e-V_9gEwYymqRldpiFk"
MyRequest.Send
Dim Json As Object
Set Json = JsonConverter.ParseJson(MyRequest.ResponseText)
MsgBox Json("stats")("id")(0)("base_stat")
I'd like to get the data from the selected array to later be able to work with it, for example from
("stats")("id")(0)("base_stat")
get
48
The Json source is on the code.
So, with JSON the [] denotes a collection you can For Each over and access by index, the {} indicates dictionaries you can For Each the dict keys of, or access items by key.
You can get a feel for the structure by pasting it into a json viewer such as this. You will need to familiarise yourself with reading json but you will see that, for that value you want, it has a path of:
json("stats")(1)("base_stat")
Note: The indexing starts at one for collections in VBA JSON though it is displays 0 in the viewer.
Reading the structure:
Option Explicit
Public Sub test()
Dim Json As Object
With CreateObject("WinHttp.WinHttpRequest.5.1")
.Open "GET", "https://pokeapi.co/api/v2/pokemon/ditto/?fbclid=IwAR2pJwAgODOlI-Gdn8pH-RDFCcUfQWiYLZIVCnP8e-V_9gEwYymqRldpiFk"
.send
Set Json = JsonConverter.ParseJson(.responseText)
End With
MsgBox Json("stats")(1)("base_stat")
End Sub
Note there are various answers on StackOverflow which provide code that will list the access paths to every item in a json structure. In particular, I remember this great answer from #tinman here. It's not a substitute for learning to read JSON but an excellent tool for aiding and checking your understanding.

VBA getting values from a collection?

I am very new to VBA and I can not figure out how to get values from a Collection.
This is my code:
Dim p As Object
Set p = JSON.parse(Response.Content)
Dim links As Object
Set links = p.Item("links")
In the debugger for "links" I see:
I am using this library to parse json : http://www.ediy.co.nz/vbjson-json-parser-library-in-vb6-xidc55680.html
The part I have in json is:
"links":[
{
"rel":"next",
"href":"www.google.com"
}
]
How can I get the value of "rel" here?
Don't forget the bang operator, designed for collection access by key:
links(1)!rel
or:
links(1)![rel] 'When there are spaces or reserved words.
I will answer my own question:
links(1).Item("rel")
worked...
Regards..
Using JavaScript features of parsing JSON, on top of ScriptControl, we can create a parser in VBA which will list each and every data point inside the JSON. No matter how nested or complex the data structure is, as long as we provide a valid JSON, this parser will return a complete tree structure.
JavaScript’s Eval, getKeys and getProperty methods provide building blocks for validating and reading JSON.
Coupled with a recursive function in VBA we can iterate through all the keys (up to nth level) in a JSON string. Then using a Tree control (used in this article) or a dictionary or even on a simple worksheet, we can arrange the JSON data as required.
You can see the full VBA code here

Source of documentation for a standard JSON document structure?

I am working on a (.NET) REST API which is returning some JSON data. The consumer of the API is an embedded client. We have been trying to establish the structure of the JSON we will be working with. The format the embedded client wants to use is something I have not seen before in working with JSON. I suggested that it is no "typical" JSON. I was met with the question "Where is 'typical' JSON format documented"?
As an example of JSON I "typically" see:
{
"item" : {
"users": [ ... list of user objects ... ],
"times": [ ... list of time objects ...],
}
}
An example of the non-typical JSON:
{
"item" : [
{
"users": [ ... list of user objects ... ]
},
{
"times": [ ... list of time objects ...]
},
]
}
In the second example, item contains an array of objects, which each contain a property whose value is an array of entities. This is valid JSON. However, I have not encountered another instance of JSON that is structured this way when it is not an arbitrary array of objects but is in fact a set list of properties on the "item" object.
In searching json.org, stackoverflow.com and other places on the interwebs I have not found any guidelines on why the structure of JSON follows the "typical" example above rather than the second example.
Can you provide links to documentation that would provide recommendations for one format or the other above?
Not a link, but just straightforward answer: Items are either indexed (0, 1, 2, ...) or keyed (users, times). No matter what software you use, you can get at indexed or keyed data equally easily and quickly. But not with what you call "non-typical" JSON: To get at the users, I have to iterate through the array and find one dictionary that has a key "users". But there might be two or more dictionaries with that key. So what am I supposed to do then? If you use JSON schema, the "non-typical" JSON is impossible to check. In iOS, in the typical case I write
NSArray* users = itemDict [#"users"];
For the non-typical JSON I have to write
NSArray* users = nil;
for (NSDictionary* dict in itemArray)
if (dict [#"users"] != nil)
users = dict [#"users"];
but that still has no error checking for multiple dicts with the key "users". Which is an error that in the first case isn't even possible. So just tell them what the are asking for is rubbish and creates nothing but unnecessary work. For other software, you probably have the same problems.

Use ScriptControl to parse JSON in VBA: transform result to dictionaries and collections

I would like to use Microsoft ScriptControl to parse a JSON string in VBA, and then transform the resulting Object into Dictionary and Collection objects. I already know how to do the parsing with ScriptControl, but cannot figure out how to map the result into the Dictionary and Collection classes. I'm guessing that if I could figure out how to loop through the properties of an Object this would become clear...
Dim sc As ScriptControl
Dim obj As Variant
Set sc = CreateObject("ScriptControl")
sc.Language = "JScript"
Set obj = sc.Eval("("+json+")") ' json is a string containing raw JSON
' Now what?
By the way, I've used the vba-json library to get the output in terms of Dictionaries and Collections, but I find this library somewhat slow. It does not use ScriptControl.
EDIT: I found a discussion of getting object properties in this post.
Using JavaScript features of parsing JSON, on top of ScriptControl, we can create a parser in VBA which will list each and every data point inside the JSON. No matter how nested or complex the data structure is, as long as we provide a valid JSON, this parser will return a complete tree structure.
JavaScript’s Eval, getKeys and getProperty methods provide building blocks for validating and reading JSON.
Coupled with a recursive function in VBA we can iterate through all the keys (up to nth level) in a JSON string. Then using a Tree control (used in this article) or a dictionary or even on a simple worksheet, we can arrange the JSON data as required.
VBA Code:http://ashuvba.blogspot.in/2014/09/json-parser-in-vba-browsing-through-net.html
loop
This will help you to loop - add a myitem(n) method in javascript
from there you can map through VB code.