I have been trying to find a way to extract rows of data from an SQL database, format the returned rows into a JSON format and post/send that to a JSON web API. I am using an asp JSON serializer for VBScript (.Flush) to transform the SQL data into JSON. It works great, I have the structure i need and I also have the method to send the JSON formatted data. So what's the issue you might ask.....
The issue is I can't send apiDefaults.flush to the webserver, it does not work. If I send the same data as a hardcoded variable it works perfectly and the API takes the data.
Let me explain some more.
Here is the JSON output I see on screen using apiDefaults.flush This is perfectly formatted exactly what i need.
{"authentication": { "apiKey": "123456789101112131415" }, "createProperties": [ { "name": "Property 1", "propKey": "6sf3zqq151n2wkah" }, { "name": "Property 2", "propKey": "yuf38zc4cls9hz19" } ] }
However, I can't get this value stored into a variable. If I could simply do the following, my issue would be resolved but you can't bind a the .flush method to a variable?!?! I don't understand why as it is just a string of text in theory.
dim myJson = apiDefaults.flush
This bit of code here is where I set the values to send to the web server, my variable that holds the JSON string
'IF I USE THIS IT WORKS PERFECTLY, IT TAKES MY MANUALLY CREATED VARIABLE/STRING AND SENDS IT
oXMLHttp.send strmultiprop
'THIS IS WHAT I FIGURED I SHOULD BE ABLE TO USE BUT IT IS NOT TREATED LIKE A VARIABLE
oXMLHttp.send apiDefaults.flush
' I TRIED THIS AND THIS WON'T WORK EITHER
oXMLHttp.send myJson
Below is my actual scripts
<% #LANGUAGE="VBSCRIPT" CODEPAGE="65001" %>
<!--#include file="JSON_2.0.4.asp"-->
<%
Function QueryToJSON(dbcomm, params)
Dim rs, jsa, aaa, bbb
Set rs = dbcomm.Execute(,params,1)
Set jsa = jsArray()
Do While Not (rs.EOF Or rs.BOF)
Set jsa(Null) = jsObject()
For Each col In rs.Fields
jsa(Null)(col.Name) = col.Value
Next
rs.MoveNext
Loop
Set QueryToJSON = jsa
rs.Close
End Function
strConn = "PROVIDER=SQLOLEDB;DATA SOURCE=LOCALHOST;UID=sa;PWD=********;DATABASE=DB_Site"
Set conn = Server.CreateObject("ADODB.Connection")
conn.Open strConn
query = "SELECT wce_uid as name, uniqueid as propKey FROM wces_users WHERE Prop_Moved = ?"
CustomerID = "Y" 'Request.QueryString("CustomerID")
arParams = array(CustomerID)
Set cmd = Server.CreateObject("ADODB.Command")
cmd.CommandText = query
Set cmd.ActiveConnection = conn
' https://stackoverflow.com/questions/40781130/setting-up-rest-api-in-classic-asp
key = "1234567891011121314151678910"
url = "https://www.beds24.com/api/json/createProperties"
'1 PROPERTY WORKING
str1prop = "{""authentication"": { ""apiKey"": ""123456789101112131415"" }, ""createProperties"": [ { ""name"": ""New Test"", ""propKey"": ""NewTest1"" } ] }"
'2 PROPERTY WORKING
strmultiprop = "{""authentication"": { ""apiKey"": ""123456789101112131415"" }, ""createProperties"": [ { ""name"": ""3333"", ""propKey"": ""3333"" }, { ""name"": ""4444"", ""propKey"": ""4444"" } ] }"
set apiDefaults = QueryToJSON(cmd, arParams)
'3 THE FLUSH METHOD --- THIS DOES NOT SET THE VRIABLE TO THE OUTPUT I SEE ON SCREEN
dim myJson = apiDefaults.flush
apiDefaults.flush
conn.Close : Set Conn = Nothing
Dim oXMLHttp
Set oXMLHttp=Server.Createobject("MSXML2.ServerXMLHTTP.6.0")
oXMLHttp.open "POST", url,false
oXMLHttp.setRequestHeader "Content-Type", "application/json"
oXMLHttp.send apiDefaults.flush 'THIS IS THE ISSUE LINE USING THIS. if I CHANGE TO strmultiprop NO ISSUES AT ALL.
response.write oXMLHttp.responseText
Set oXMLHttp = Nothing
%>
Any advice on this would be great.
Thanks for looking.
My question was answered by #SearchAndResQ
"Try oXMLHttp.send apiDefaults.jsString, you need the value in that property"
Related
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
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
good people of StackOverflow!
I am trying to figure out how to connect to Airtable API, get JSON from there and populate Access table with the results.
So far, at least I managed to restrict the request to give me only a few fields I need.The result looks like this:
{
"records": [{
"id": "rec008lgyvVmwk1F4",
"fields": {
"Date": "2018-02-28"
},
"createdTime": "2018-01-26T15:36:23.000Z"
}, {
"id": "rec02WozJeaGvfBfj",
"fields": {
"Hours": 1.5,
"Date": "2018-02-09",
"Project": ["Nonbillable"]
},
"createdTime": "2018-02-12T17:03:18.000Z"
}, {
"id": "rec05VxP0CYTsDYOA",
"fields": {
"Date": "2018-02-08"
},
"createdTime": "2018-02-01T10:29:52.000Z"
}, {
"id": "rec05xoQEm5iWIYmz",
"fields": {
"Hours": 0.75,
"Date": "2018-02-16",
"Project": ["2018 - Japan DLAs"]
},
"createdTime": "2018-02-19T09:29:18.000Z"
}]
}
From that point on I have read as many examples as I could find how to use VBA-JSON by Tim Hall (thank you Tim, for creating it :)
As far as I understand, in my case the ParseJson function returns a dictionary. Inside that is a collection named 'results' and inside that collection is another dictionary named 'fields'.
What I need are values for keys 'Hours', 'Date' and 'Project' from that dictionary.
I have tried to do those three loops (loop through dictionary inside collection inside dictionary) and was failing miserably many times with a variety of errors. Finally, I have come to the point where I see no more errors, the sub happily gives me "Import done!" message. Alas, my table is empty!
What, what am I doing wrong?
I hope I gave you enough information and thank you very much in advance for your help!
(If it matters, I'm working with 32-bit Access 2016 on 64-bit Windows)
Public Sub ImportJSON()
Dim reader As New XMLHTTP60
Dim JsonRetrieved As String
Dim Parsed As Scripting.Dictionary
Dim records As New Collection
Dim fields As Scripting.Dictionary
Dim item As Variant
Dim rs As New ADODB.Recordset
reader.Open "GET", "https://api.airtable.com/v0/apppLTTgKBsw5QmUX/myTable?fields[]=Project&fields[]=Hours&NOT({Hours} = '')&fields[]=Date&NOT({Date} = '')&maxRecords=4&api_key=mykey", False
reader.setRequestHeader "Accept", "application/json"
reader.Send
Do Until reader.ReadyState = 4
DoEvents
Loop
If reader.Status = 200 Then
rs.Open "tblAirtableImport", CurrentProject.Connection, _
adOpenKeyset, adLockOptimistic
JsonRetrieved = reader.responseText
'Debug.Print JsonRetrieved
Set Parsed = JsonConverter.ParseJson(JsonRetrieved)
'loop through dictionary 'Parsed'
Dim i As Long
For i = 0 To Parsed.Count - 1
'loop through collection 'records'. If we have hours logged into Airtable add new record (Hours, Date, Project) to Access table
For Each fields In records
'loop through dictionary 'fields'
Dim j As Long
For j = 0 To fields.Count - 1
If fields.Exists("Hours") Then
'MsgBox "We have hours in this row"
rs.AddNew
rs!AirtableHours = fields.item("Hours")
rs!AirtableDate = fields.item("Date")
rs!AirtableProject = fields.item("Project")
rs.Update
Else
MsgBox "No logged time."
End If
Next j
Next
Next i
MsgBox "Import done!"
Set Parsed = Nothing
Else
MsgBox "Ups, unable to import data. Reader status is: " & reader.Status
End If
End Sub
The entry Project holds an Array so take the first Item:
Set Parsed = JsonConverter.ParseJson(JsonRetrieved)
For Each record In Parsed("records")
Set fields = record("fields")
If fields.Exists("Hours") Then
rs.AddNew
rs!AirtableHours = fields("Hours")
rs!AirtableDate = fields("Date")
rs!AirtableProject = fields("Project")(1)
rs.Update
End If
Next
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
After looking at several questions/answers here, I'm not seeing what I think I need. I have a page posting to an asp server page via ajax. The returning json string is showing up in the console on Firefox. I can see the post data going to the asp page, I can see the response which is
{ "firstname": "Christopher","lastname": "Romero","email": "cromero#marketscout.com","adminlvl": "00","message": "Thanks for logging in!" }
I can also see the values of the string above in the JSON tab in Console --> ALL --> JSON. There are no errors being reported inside the console. Here is my javascript:
$('#loginsub').click(function() {
$.ajax({
url: "logincheck.asp",
type: "POST",
data: $('#loginform').serialize(),
dataType: "json",
success: function(data) {
console.log(data);
//alert(data.firstname + ' ' + data.lastname);
//alert(data[0].firstname + ' ' + data[0].lastname);
$.trim(data);
var json = $.parseJSON(data);
alert(json.firstname);
}
});
});
Here is the asp that is running on the server on logincheck.asp:
set cmd = Server.CreateObject("ADODB.Command")
with cmd
.ActiveConnection = cnnopen
.CommandText = storedproc
.CommandType = adCmdStoredProc
dim intCount,intItem
for each item in odcformdata
select case vartype(odcformdata(item)) 'this is searching for the correct data type to put into the parameter [type] argument below. (integers, currency, dates, & strings)
case 2 : .Parameters.Append .CreateParameter("#"&cstr(item),adInteger,adParamInput,len(odcformdata(item)),odcformdata(item))
case 6 : .Parameters.Append .CreateParameter("#"&cstr(item),adCurrency,adParamInput,len(odcformdata(item)),odcformdata(item))
case 7 : .Parameters.Append .CreateParameter("#"&cstr(item),adDate,adParamInput,len(odcformdata(item)),odcformdata(item))
case 8 : .Parameters.Append .CreateParameter("#"&cstr(item),adVarChar,adParamInput,len(odcformdata(item)),odcformdata(item))
end select
next
end with
set rs = cmd.execute
'do stuff with returned results from select or leave blank if insert/delete/etc stored procedure
if rs.EOF = false then
'Build json array based on fields returned from stored proc.
dim arrJSON
arrJSON = "{ "
while not rs.EOF
for each fields in rs.Fields
arrJSON = arrJSON & """" & fields.name & """: """ & fields & ""","
next
rs.movenext
wend
arrJSON = arrJSON & """message"": ""Thanks for logging in!"","
arrJSON = left(arrJSON, len(arrJSON)-1) & " }"
response.write arrJSON
end if
set rs = nothing
set cmd = nothing
odcformdata.removeall
The alerts() in the javascript are not returning values that I would expect, I'm getting [object Object] returning on the alert when I'm expecting the JSON array/string to get printed out.
Anyone with some advice for me? I'm a jquery rookie and getting better, but this is getting on my nerves!
What does your first console.log(data) show?
This works for me:
http://jsfiddle.net/2tvCf/