A small question: i'm using JsonConverter from Github.
(https://github.com/VBA-tools/VBA-JSON/blob/master/JsonConverter.bas)
Code is working on most of the "GET" request.
Only when the same 'column' is accuring multiple times in the 'ResponseText' then it's not. (like "imei" in the example)
So I need a way to handle a long 'Responsetext' to fill multiple rows in an access db.
Dim Json As Object
Set Json = JsonConverter.ParseJson(xmlhttp.ResponseText)
MsgBox (Json("imei")) 'temp
Error 5: Invalid Procedure or Call Argument.
Any ideas?
Many thanks,
I can only provide a part of the answer, because I cannot recreate it, without the full JSON Response Text:
The response with mutliple values in JSON returns an Object of the type Collection. Hence you have to use a loop to iterate through all responses. Like this:
Dim Json As Object
Set Json = JsonConverter.ParseJson(xmlhttp.ResponseText)
For Each singleJsonItem In Json
'What object type is singleJsonItem? To find out, maybe use:
'MsgBox singleJsonItem("imei")
Next singleJsonItem
You have to find out the object type of the collectionentries to extract the JSON Entry.
Solved like this:
used : https://github.com/VBA-tools/VBA-JSON
and named the module: 'mdl_JsonConverter'
Set Json = mdl_JsonConverter.ParseJson(xmlhttp.ResponseText)
For Each item In Json
input_1 = item("input_1")
input_2 = item("input_2")
'THEN DO SOMETHING WITH VALUES F.E. ADDING THEM IN A TABLE
Next
If you responseText contains a searchRecords list then filter by searchRecords before for each
Set Json = JsonConverter.ParseJson(strResponse)
For Each singleJsonItem In Json("searchRecords")
'What object type is singleJsonItem? To find out, maybe use:
Msgbox singleJsonItem("Name")
Next singleJsonItem
So I have a request to a JSON api working using client-side jquery and AJAX. Unfortunately, another api insists this be done from the server because of security concerns regarding the token. I'm a bit stumped. To begin, what I got working from client-side JavaScript looks like:
$.getJSON("https://api.xyz.com/mytoken/specificargument",function(data){...})
The function then fills data with JSON fields (or are they called properties?) as data.field1, data.field2, etc. These are then placed into their appropriate inputs with jquery code that lives inside the {...}. It's very straightforward.
I have read that this (i.e., obtaining the JSON string, not parsing it) can be done on the server with
Set objJSON = jsObject()
objJSON("apikey") = "mytoken"
Set objJSON("arg1") = jsObject()
objJSON("arg1")("arg1") = "specificargument"
set objXMLhttp = Sever.Createobject("MSXML2.ServerXMLHTTP")
objXMLhttp.open "POST","https://api.abc.com", false
objXMLhttp.setRequestHeader "Content-type","application/json"
objXMLhttp.setRequestHeader "Accept","application/json"
objXMLhttp.send objJSON.jsString
strResponse = objXMLhttp.responseText
Set objXMLhttp = Nothing
So that's pretty useful, except the posting says I need to use "appropriate declarations, includes, etc." So I thought it would be simple to find these, but querying for classic ASP JSON yields very confusing results. Can someone help with these:
what do I need to do to properly use the aspjson library for the above?
how do I pass "specificargument" above. What I've written is a bit of a mess and I'm sure incorrect. On the client side, the token and argument are part of the querystring. How does this work for the jsObject?
Thank you.
The example code you have posted appears to be using the aspjson - JSON serializer for VBScript based ASP server technology library. One key thing in that statement is "JSON Serializer", it will only serialise from object to string, not the other way around which makes it kind of useless for most scenarios.
This is purely my opinion but a well-maintained library that will do both is JSON object class By RCDMK. The examples on the GitHub page are pretty simple to follow, but there are some examples of its usage on this very site.
Here is a quick example of its usage inside an ASP page;
<% Option Explicit %>
<!-- #include virtual="/scripts/jsonObject.class.asp" -->
<%
Dim JSON, parsedJSON
Dim jsonString: jsonString = "[{ ""strings"" : ""valorTexto"", ""numbers"": 123.456, ""arrays"": [1, ""2"", 3.4, [5, 6, [7, 8]]], ""objects"": { ""prop1"": ""outroTexto"", ""prop2"": [ { ""id"": 1, ""name"": ""item1"" }, { ""id"": 2, ""name"": ""item2"", ""teste"": { ""maisum"": [1, 2, 3] } } ] } }]"
Call init()
Sub init()
Response.LCID = 2057
Set JSON = New JSONobject
Call Response.Write("<h2>JSON String</h2>")
Call Response.Write("<pre>" & jsonString & "</pre>")
Call Test_ParseJSON()
Call Test_WriteJSON()
End Sub
Sub Test_ParseJSON()
Call Response.Write("<h2>Parsing JSON</h2>")
Set parsedJSON = JSON.Parse(jsonString)
Call Response.Write("<pre>parsedJSON(0).Value(""objects"").Value(""prop1"") = """ & parsedJSON(0).Value("objects").Value("prop1") & """</pre>")
End Sub
Sub Test_WriteJSON()
Call Response.Write("<h2>Writing JSON</h2>")
Call parsedJSON(0).Value("objects").Change("prop1", "hello test")
Call Response.Write("<pre>" & parsedJSON.Serialize() & "</pre>")
End Sub
%>
Outputs:
JSON String
[{ "strings" : "valorTexto", "numbers": 123.456, "arrays": [1, "2", 3.4, [5, 6, [7, 8]]], "objects": { "prop1": "outroTexto", "prop2": [ { "id": 1, "name": "item1" }, { "id": 2, "name": "item2", "teste": { "maisum": [1, 2, 3] } } ] } }]
Parsing JSON
parsedJSON(0).Value("objects").Value("prop1") = "outroTexto"
Writing JSON
[{"strings":"valorTexto","numbers":123.456,"arrays":[1,"2",3.4,[5,6,[7,8]]],"objects":{"prop1":"hello test","prop2":[{"id":1,"name":"item1"},{"id":2,"name":"item2","teste":{"maisum":[1,2,3]}}]}}]
From the original poster: Typically, my situation may not generalize well, but because I found a very simple solution, I'll post it here in case it helps anybody else finding this.
First of all, for this particular api, the token and other argument were passed in the querystring and the method was GET, not POST. Thus the .send command had no argument. That's all it took to get the JSON string returned. Thus:
set objXMLhttp = Server.Createobject("MSXML2.ServerXMLHTTP")
objXMLhttp.open "GET","https://api.abc.com/argument1/?token=mysecret", false
objXMLhttp.setRequestHeader "Content-type","application/json"
objXMLhttp.setRequestHeader "Accept","application/json"
objXMLhttp.send
strResponse = objXMLhttp.responseText
By the way, if I HAD needed to send a JSON-formatted argument, as has been pointed out by others, often (for simple structures) it is easy to simply create this instead of using a 3rd-party library. (E.g., from a post on this site: {"Email":"asdf#hotmail.com", "firstname":"joe", "lastname":"smith"} ).
Finally, just as it is easy to create simple JSON strings, returned data, if simple, can easily be parsed. In my case, the return always had a brace at the beginning and end, then was a simple JSON comma-delimited list of colon-pairs. This was easily split into a vbscript array (remember, my post was for classic ASP) and parsed into a dictionary (ParseJSON) as follows (note I needed to strip off all the quotation marks):
strResponse = Left(strResponse,Len(strResponse)-1) ' remove right-brace
strResponse = Right(strResponse,Len(strResponse)-1)
Dim ParseJSON
Set ParseJSON = CreateObject("Scripting.Dictionary")
ParseJSON.CompareMode = vbTextCompare
ArryJSON = Split(strResponse,",")
' parse into a dictionary
For Each jPair In ArryJSON
' take jPair apart and insert into dictionary
onePair = Split(jPair,":")
aa = onePair(0)
aa = Left(aa,Len(aa) - 1) ' remove quotation mark
aa = Right(aa,Len(aa) - 1)
bb = onePair(1)
bb = Left(bb,Len(bb) - 1)
bb = Right(bb,Len(bb) - 1)
ParseJSON.Add aa,bb
Next
This feels like it should be really simple but I'm a bit stuck. I want to access an API url using Excel VBA. The API gives me a very simple JSON response containing a load id which is used as a parameter in the calling of another API, the other API isn't a problem because I can get the response in either XML or CSV and parse it into Excel.
API Response:
{"loadid":"1234567890"}
All I need to extract from this response is the number "1234567890".
This is what I've tried so far:
Sub getLoadID()
Dim loadID As String
Dim loadIDUrl As String
loadIDUrl = "blah blah"
proxyServer = Worksheets("Sheet1").Range("A1").Value
Set httpReq = CreateObject("WinHttp.WinHttprequest.5.1")
httpReq.Open "GET", loadIDUrl, False
httpReq.setRequestHeader "Content-Type", "text/xml"
httpReq.setProxy 2, proxyServer, ""
httpReq.setTimeouts -1, -1, -1, -1
httpReq.send request
httpReq.ResponseText = loadID
Worksheets("Sheet1").Range("A2").Value = loadID
End Sub
I've tried to put the whole string into a cell just to make sure that Excel is able to obtain the string from the response but going forward will just be happy to store the value as a variable and not write it to the sheet.
The above code runs with no errors, I just don't get the string in cell A2...
Every time I've searched about parsing JSON using Excel VBA everyone recommends to use external libraries but I'm trying to do this at work so I can't use the external libraries.
Cheers
I am working with the Google Translation API, which returns results in JSON format - e.g.
{
"data": {
"translations": [
{
"translatedText": "Hola mundo"
},
{
"translatedText": "Te amo"
},
{
"translatedText": "queso"
}
]
}
}
I am trying to parse the JSON data using Classic ASP.
I'm using ASPJSON (http://www.aspjson.com/) to parse the JSON data.
I can get so far with reading the data - e.g. (where "BackFromGoogle") is the objXML.responseText from a MSXML2.ServerXMLHTTP call.
Set oJSON = New aspJSON
oJSON.loadJSON(BackFromGoogle)
For Each translation In oJSON.data("data") 'iterate through data
Set this = oJSON.data("data").item(translation)
Next
If I then try:
For Each translation In oJSON.data("data") 'iterate through data
Set this = oJSON.data("data").item(translation)
Response.Write this.item("translations").item("translatedText")
Next
Then I get this error:
Microsoft VBScript runtime error '800a01a8'
Object required: '[undefined]'
For this line:
Response.Write this.item("translations").item("translatedText")
I am very stuck working out the syntax to allow me to access the individual values of the "translatedText" lines.
Is it possible to access them?
Got this working in the end.
Found the answer via the solution here:
VbScript Deserialize JSON
This sorted it:
Set oJSON = New aspJSON
oJSON.loadJSON(BackFromGoogle)
For Each result In oJSON.data("data")("translations")
Set this = oJSON.data("data")("translations").item(result)
response.Write this.item("translatedText") & "<br>"
Next
Is it possible to script JSON calls in a macro?
I want to get a JSON string through an API connection. It looks like the problem is Excel expects the parameters to be passed in the HTML-string, but JSON passes parameters in the HTML body. Any ideas?
Since this is VBA, I'd use COM to call xmlhttprequest but use it in synchronous manner as not to upset VBA’s single threaded execution environment, A sample class that illustrates a post and get request in this manner follows:
'BEGIN CLASS syncWebRequest
Private Const REQUEST_COMPLETE = 4
Private m_xmlhttp As Object
Private m_response As String
Private Sub Class_Initialize()
Set m_xmlhttp = CreateObject("Microsoft.XMLHTTP")
End Sub
Private Sub Class_Terminate()
Set m_xmlhttp = Nothing
End Sub
Property Get Response() As String
Response = m_response
End Property
Property Get Status() As Long
Status = m_xmlhttp.Status
End Property
Public Sub AjaxPost(Url As String, Optional postData As String = "")
m_xmlhttp.Open "POST", Url, False
m_xmlhttp.setRequestHeader "Content-type", "application/x-www-form-urlencoded"
m_xmlhttp.setRequestHeader "Content-length", Len(postData)
m_xmlhttp.setRequestHeader "Connection", "close"
m_xmlhttp.send (postData)
If m_xmlhttp.readyState = REQUEST_COMPLETE Then
m_response = m_xmlhttp.responseText
End If
End Sub
Public Sub AjaxGet(Url As String)
m_xmlhttp.Open "GET", Url, False
m_xmlhttp.setRequestHeader "Connection", "close"
m_xmlhttp.send
If m_xmlhttp.readyState = REQUEST_COMPLETE Then
m_response = m_xmlhttp.responseText
End If
End Sub
'END CLASS syncWebRequest
So now you can call the above to return you the server's response:
Dim request As New syncWebRequest
request.ajaxGet "http://localhost/ClientDB/AllClients?format=json"
Dim json as string
json = request.Response
The problem here is we want to be able to read the data returned from the server in some way, more so than manipulating the JSON string directly. What's worked for me is using the VBA-JSON (google code export here) COM type Collection to handle JSON arrays and Dictionary to handle members and their declarations, with a parser factory method Parse that basically makes creating these collections of dictionaries much simpler.
So now we can parse the JSON:
[{"Name":"test name","Surname":"test surname","Address":{"Street":"test street","Suburb":"test suburb","City":"test city"}}]
into something like the following:
Set clients = parser.parse(request.Response)
For Each client In clients
name = client("Name")
surname = client("Surname")
street = client("Address")("Street")
suburb = client("Address")("Suburb")
city = client("Address")("City")
Next
That's nice but what about stuff like being able to edit and post back the data? Well there's also a method toString to create a JSON string from the above [Collection/Dictionary] JSON data, assuming the server accepts JSON back.
I wrote a .NET Excel-Addin for this. It's a generic Excel JSON client that streams any JSON object straight into Excel via http.
Docs and installation instructions can be found here:
http://excel-requests.pathio.com/en/master/
And here's the GitHub link:
https://github.com/ZoomerAnalytics/excel-requests