How to send a byte array as json using Visual Basic 6? - json

I have an Visual Basic 6 application which should read a file into a byte array, put that into a json object and make a post request to a rest API. I have everything working except the byte array part. When I use the code below, the API just receives the string "bytes" and not the actual content of the request that should look something like this "JVBERi0xLjQKJeLjz9MKCj"
Private Function PostDocumentPrint() As String
'Create http client
Dim http As Object
Set http = CreateObject("WinHttp.WinHttprequest.5.1")
url = "XXX"
http.Open "Post", url, False
'Set request parameters
http.SetRequestHeader "charset", "UTF-8"
http.SetTimeouts 500, 500, 500, 500
' Read file into byte array
Dim fileNum As Integer
Dim bytes() As Byte
fileNum = FreeFile
Open "FileToSend.pdf" For Binary As fileNum
ReDim bytes(LOF(fileNum) - 1)
Get fileNum, , bytes
Close fileNum
' Send the request
Dim jsonStringPostBody As String
jsonStringPostBody = " {""fileData"": "" " + bytes + """} "
http.Send jsonStringPostBody
End Function
I believe I need to convert the byte array to a string somehow. For example I tried this:
Dim s As String
s = StrConv(bytes, vbUnicode)
MsgBox s
But it does not look correct.

Related

Excel data parsing says error expecting '{' or '['

Here is my Code i have tried many searching but didnt find right solution please help there.
Sub JnewCOP22()
Dim req As New MSXML2.XMLHTTP60
Dim URL As String, ws As Worksheet
Dim json As Object, r, r1 As String, i, j As Integer
URL = "https://www.nseindia.com/api/quote-equity?symbol=DRREDDY&section=trade_info"
With req
.Open "GET", URL, False
.send
Set json = JsonConverter.ParseJson(.responseText)
r = json("securityWiseDP")("quantityTraded")
End With
MsgBox r
End Sub
The API Data
{"noBlockDeals":true,"bulkBlockDeals":[{"name":"Session I"},{"name":"Session II"}],"marketDeptOrderBook":{"totalBuyQuantity":0,"totalSellQuantity":264,"bid":[{"price":0,"quantity":0},{"price":0,"quantity":0},{"price":0,"quantity":0},{"price":0,"quantity":0},{"price":0,"quantity":0}],"ask":[{"price":4659.2,"quantity":264},{"price":0,"quantity":0},{"price":0,"quantity":0},{"price":0,"quantity":0},{"price":0,"quantity":0}],"tradeInfo":{"totalTradedVolume":1945164,"totalTradedValue":92498.58,"totalMarketCap":7713541.51,"ffmc":5659504.6195251,"impactCost":0.02},"valueAtRisk":{"securityVar":10.89,"indexVar":0,"varMargin":10.89,"extremeLossMargin":3.5,"adhocMargin":0,"applicableMargin":14.39}},"securityWiseDP":{"quantityTraded":1945164,"deliveryQuantity":417789,"deliveryToTradedQuantity":21.48,"seriesRemarks":null,"secWiseDelPosDate":"29-OCT-2021 EOD"}}
The error massage says error parsing json <!Doctype h ^ expecting ' {' or '[ '
It seems that your request does not return JSON as you expected, but rather an ordinary HTML document.
In order to request a JSON document, you (probably) should set the HTTP request header Accept to application/json.

VBA post method request body ("MSXML2.XMLHTTP"): Error Parsing JSON: ^ Expecting '{' or '['

I'm trying to retrieve a JSON response object through the below query API. When I try to read the responseText in VBA I receive an empty result. However, the exact same request returns correct data from PostMan. Also, the correct data returns from sending the different request bodies. Whenever I try to execute Set Json = JsonConverter.ParseJson(strResponse) and I'm getting the error message Error Parsing JSON: ^ Expecting '{' or '['. Can you please help?
This is VBA code
Dim strUrl As String
Dim reqBody As String
'For search GOSS service API-Step1
strUrl = "https://gossrepo.ins.dell.com/gossv3/api/reporting/service/getrefid"
'create a method for calling HTTP services
Set hReq = CreateObject("MSXML2.XMLHTTP")
With hReq
.Open "POST", strUrl, blnAsync, False
reqBody = "{""methodType"":extract,""sourceApplication"":DSA,""searchParameter"":[{""conditionType"":term,""key"":global_bu_id,""value"":11},{""conditionType"":wildcard,""key"":customer_num,""value"":[530007546697]},{""conditionType"":range,""key"":order_date,""value"":[{""from"":2021-08-31,""to"":2021-09-09}]},{""conditionType"":sort,""key"":order_date_time,""value"":desc}],""pageSize"":40,""pageNum"":0}"
.SetRequestHeader "Content-type", "application/json"
.Send reqBody
While hReq.ReadyState <> 4
DoEvents
Wend
'wrap the response in a JSON root tag "data" to count returned objects
strResponse = hReq.ResponseText
Debug.Print strResponse
End With
Set Json = JsonConverter.ParseJson(strResponse)
Updated the fixed with the different post body:
Dim strUrl As String
Dim reqBody As String
'For search GOSS service API-Step1
strUrl = "https://gossrepo.us.dell.com/gossv3/api/reporting/service/getdata"
'create a method for calling HTTP services
Set hReq = CreateObject("MSXML2.XMLHTTP")
With hReq
.Open "POST", strUrl, blnAsync, False
reqBody = "{""methodType"":""details"",""sourceApplication"":""DSA"",""pageNum"":0,""pageSize"":300,""searchParameter"":[{""conditionType"":""term"",""key"":""global_bu_id"",""value"":""11""},{""conditionType"":""wildcard"",""key"":""customer_num"",""value"":[""" & ws & """]},{""conditionType"":""range"",""key"":""order_date"",""value"":[{""from"":""" & ws11 & """,""to"":""" & ws12 & """}]},{""conditionType"":""sort"",""key"":""order_date_time"",""value"":""desc""}]}"
.SetRequestHeader "Content-type", "application/json"
.Send reqBody
While hReq.ReadyState <> 4
DoEvents
Wend
'wrap the response in a JSON root tag "data" to count returned objects
strResponse = hReq.ResponseText
End With
Set Json = JsonConverter.ParseJson(strResponse)
Probably your request is wrong and you don't get the expected response because of it... Look at the status that's returned (hReq.status and hReq.statusText), I bet it's 400 Bad Request or 500 Internal Error and not 200 Ok. (You could also use an inspecting proxy like Fiddler to look at what exactly you send and receive here.)
I can already see your request body is invalid JSON as it has unquoted strings in it... It's not the exact same as you showed in Postman! That's like the issue (or one of the issues). You have e.g. "methodType": extract, but it has to be "methodType": "extract" (in VBA ""methodType"": ""extract"") - you did it correctly in Postman but wrong in your code.
As mentioned by CherryDT - Your original reqBody had alot of missing quotes and in your updated reqBody, you are missing quotes for order_date and also you quoted pageSize and pageNum value which is supposed to be a number and thus quotes is not required:
Below should give you the same JSON string as what you had in Postman:
reqBody = "{""methodType"":""extract"",""sourceApplication"":""DSA"",""searchParameter"":[{""conditionType"":""term"",""key"":""global_bu_id"",""value"":""11""},{""conditionType"":""wildcard"",""key"":""customer_num"",""value"":[""530007546697""]},{""conditionType"":""range"",""key"":""order_date"",""value"":[{""from"":""2021-08-31"",""to"":""2021-09-09""}]},{""conditionType"":""sort"",""key"":""order_date_time"",""value"":""desc""}],""pageSize"":40,""pageNum"":0}"
One way which has been working well for me so far is:
Copy the JSON string from Postman to Notepad
Open Replace dialog (Ctrl-H)
Enter " in Find What
Enter "" in Replace with
Click Replace All
Now you can copied the new string back to your VBA editor and it should produce the same output as Postman's.

JSON to VBA - Error 13 mismatch on "root values"

I was trying to get some information from a JSON API and everything was going OK. So I started to get mismatch errors when I try to parse values that are inside the “root” of the JSON.
The code I use is below:
Public Sub Times()
Dim http As Object, JSON As Object, i As Integer
Set http = CreateObject("MSXML2.XMLHTTP")
http.Open "GET", "https://api.cartolafc.globo.com/time/id/1084847/7", False
http.Send
Set JSON = ParseJson(http.responseText)
i = 2
Application.ScreenUpdating = False
Sheets("Youtube").Select
For Each Item In JSON
Sheets("Mais Escalados").Cells(i, 2).value = Item("pontos")
i = i + 1
Next
Application.ScreenUpdating = True
MsgBox ("Atualização Completa")
End Sub
I can parse the data inside atletas sub-items or any other header changing the code like this:
Sheets("Mais Escalados").Cells(i, 2).value = Item("atletas")("nome")
But when I try to parse information like pontos on the root I get the mismatch error.
This will give you the root value for the key "pontos":
JSON("pontos")
You can't loop over the root keys like you show in your posted code: you would need to check the type of each key's value before you try to write it to the sheet:
Public Sub Times()
Dim http As Object, JSON As Object, i As Integer, k
Set http = CreateObject("MSXML2.XMLHTTP")
http.Open "GET", "https://api.cartolafc.globo.com/time/id/1084847/7", False
http.Send
Set JSON = ParseJson(http.responseText)
For Each k In JSON
Debug.Print k, TypeName(JSON(k))
Next
End Sub
Output:
atletas Collection
clubes Dictionary
posicoes Dictionary
status Dictionary
capitao_id Double
time Dictionary
patrimonio Double
esquema_id Double
pontos Double
valor_time Double
rodada_atual Double

Send JSON file in HTTP (VB6)

I can now able to send the pure text in HTTP using this code..
Public Function WebRequest(url As String, jsonFile As String) As String
'In this string, I am putting the parsed JSON file
jsonFile = ReadTextFile(jsonFile)
Dim http As MSXML2.XMLHTTP60
Set http = CreateObject("MSXML2.ServerXMLHTTP")
http.Open "POST", url, False
http.send jsonFile
WebRequest = http.responseText
Set http = Nothing
End Function
This function is just to parse the JSON file, I have CommonDialog control for choosing the file.
Public Function ReadTextFile(sFilePath As String) As String
On Error Resume Next
Dim handle As Integer
If LenB(Dir$(sFilePath)) > 0 Then
handle = FreeFile
Open sFilePath For Binary As #handle
ReadTextFile = Space$(LOF(handle))
Get #handle, , ReadTextFile
Close #handle
End If
End Function
That simple code will successfully POST a text in HTTP, but what I want is to post the exact JSON file, not just the text inside of it.

Microsoft Cognitive API document size limit of 10240 bytes

When submitting a document to the API for key phrases, the returned JSON response has the error "A document within the request was too large to be processed. Limit document size to: 10240 bytes."
According to https://learn.microsoft.com/en-us/azure/cognitive-services/cognitive-services-text-analytics-quick-start, "The maximum size of a single document that can be submitted is 10KB, and the total maximum size of submitted input is 1MB. No more than 1,000 documents may be submitted in one call."
The document in question is a string of length 7713. The byte length using Encoding.UTF8.GetBytes() is 7763.
The entire byteArray that is submitted is of length 7965.
Smaller strings work fine, but any strings greater than length 3000 seem to have this problem. Below is the code, written in VB.NET:
' Create a JSONInput object containing the data to submit
Dim myJsonObject As New JSONInput
Dim input1 As New JSONText
input1.id = "1"
input1.text = text
myJsonObject.documents.Add(input1)
' Translate the JSONInput object to a serialized JSON string
Dim jss As New JavaScriptSerializer()
Dim jsonString As String = jss.Serialize(myJsonObject)
' Windows Cognitive Services URL
Dim request As System.Net.WebRequest = System.Net.WebRequest.Create("https://westus.api.cognitive.microsoft.com/text/analytics/v2.0/keyPhrases")
' Set the Method property of the request to POST.
request.Method = "POST"
' Add a header with the account key.
request.Headers.Add("Ocp-Apim-Subscription-Key", accountKey_TextAnalytics)
' Create POST data and convert it to a byte array.
Dim postData As String = jsonString
Dim byteArray As Byte() = Encoding.UTF8.GetBytes(postData)
' Set the ContentType property of the WebRequest.
request.ContentType = "application/json"
' Set the ContentLength property of the WebRequest.
request.ContentLength = byteArray.Length
' Get the request stream.
Dim dataStream As System.IO.Stream = request.GetRequestStream()
' Write the data to the request stream.
dataStream.Write(byteArray, 0, byteArray.Length)
' Close the Stream object.
dataStream.Close()
' Get the response.
Dim response As System.Net.WebResponse = request.GetResponse()
' Get the stream containing content returned by the server.
dataStream = response.GetResponseStream()
' Open the stream using a StreamReader for easy access.
Dim reader As New System.IO.StreamReader(dataStream)
' Read the content.
Dim responseFromServer As String = reader.ReadToEnd()
' Display the content.
Console.WriteLine(responseFromServer)
' Clean up the streams.
reader.Close()
dataStream.Close()
response.Close()
' Deserialize the json data
jss = New JavaScriptSerializer()
Dim jsonData = jss.Deserialize(Of Object)(responseFromServer)
' List of key phrases to be returned
Dim phrases As New List(Of String)
For Each item As String In jsonData("documents")(0)("keyPhrases")
phrases.Add(item)
Next
Return phrases
My question is, what might I be doing wrong here, that I'm receiving messages that my document is exceeding the size limit of 10240 bytes, but it appears that the data that I POST is well under that limit.
As Assaf mentioned above, please make sure to specify UTF-8 encoding.