How to save a json file from an API in vb.net - json

I have an API where I consume a Json file from. The function I have written is
Public Function getData(ByVal _token As String, ByVal _identifier As String) As String
Dim client = New RestClient(_baseURI)
Dim request = New RestRequest("/datasources/{identifier}/data", Method.GET)
request.AddUrlSegment("identifier", _identifier)
request.AddHeader("Authorization", "Basic " + _token)
Dim jstr = client.Execute(request).Content
Dim allDATA As List(Of GeneralInfo) = JsonConvert.DeserializeObject(Of List(Of GeneralInfo))(jstr)
Return 0
End Function
This works perfectly well. I can save the string into a file. But I also need a json file and I just do not know how to accomplish this.
Based on this solution I tried
request.OnBeforeDeserialization = Function(resp)
resp.ContentType = "appliction/json"
End Function
Dim queryResult = client.Execute(request)
Console.WriteLine(queryResult.Content)
but without any result. Nothing will be written into the console. Any idea how I can get the json file? I am using
Imports Newtonsoft.Json
Imports RestSharp

Related

Json with parameters in Vb.net

I need to send json data to an API including a QR code and some other values.
this is what i got from them
The needed parameter is:
• Parameter "data" in JSON:
id -> 100 (fixed, it is the ID needed for our software)
qrcode -> QRcode value
Example: data={"id":"100","qrcode":"VL11bbdb186a3a6dcfc57a1b07149c9a0e"}
and this is the code i use
Call:
Dim jsonPost As New JsonPost(postadress)
Dim dictqr As New Dictionary(Of String, Object)
dictqr.Add("id", lastmeas.id)
dictqr.Add("qrcode", lastmeas.qrcode)
jsonPost.PostData(dictqr)
and this is the definition
Public Class JsonPost
Private urlToPost As String = ""
Public Sub New(ByVal urlToPost As String)
Me.urlToPost = urlToPost
End Sub
Public Function PostData(ByVal dictData As Dictionary(Of String, Object)) As Boolean
Dim webClient As New WebClient()
Dim resByte As Byte()
Dim resString As String
Dim reqString() As Byte
ServicePointManager.ServerCertificateValidationCallback = Function(o, certificate, chain, errors) True
Try
webClient.Headers("content-type") = "application/json"
webClient.Headers("accept") = "*/*"
reqString = Encoding.Default.GetBytes(JsonConvert.SerializeObject(dictData, Newtonsoft.Json.Formatting.None))
resByte = webClient.UploadData(Me.urlToPost, "POST", reqString)
resString = Encoding.Default.GetString(resByte)
Form1.respuesta_envio = resString
webClient.Dispose()
Return True
Catch ex As Exception
Form1.respuesta_envio = ex.Message
CreateObject("WScript.Shell").Popup(ex.Message, 5, "Data not transfered")
End Try
Return False
End Function
End Class
if i deserialize, i get
{"id":"100","qrcode":"example"}
but i do not know how to include this data= part
The API appears to be asking you to send a JSON string inside a form-url-encoded parameter. That's unpleasant and not a logical way to design an API, but if that's what they require then that's what you'll have to do.
Therefore you need to:
remove the Content-Type header telling the server to expect a JSON body in the request. What you'll actually be sending is form-url-encoded data where the one parameter happens to contain JSON within its value. i.e. remove this line:
webClient.Headers("content-type") = "application/json"
prepend the data= bit to the JSON string generated by the SerializeObject function:
reqString = Encoding.Default.GetBytes("data=" & JsonConvert.SerializeObject(dictData, Newtonsoft.Json.Formatting.None))

Serialized JSON in VB.NET not recognised by web server

I'm new to VB.NET and am working on a simple program that will serialize two variables into JSON and POST the data to a web server. The data is being received by the Python server but it is giving an error when trying to deserialize the data.
The inputs are:
tester_id = 2
operation = "P"
When serialized this looks like:
{
"tester_id": 2,
"operation": "P"
}
Our server is giving an error and has the following log.
[Sat Aug 19 13:46:53.485257 2017] [:error] [pid 17352] <QueryDict: {u'{\\r\\n "tester_id": 2,\\r\\n "operation": "P"\\r\\n}': [u'']}>
This suggests that it is receiving a key of:
{u'{\\r\\n "tester_id": 2,\\r\\n "operation": "P"\\r\\n}
With a value of:
[u'']
This isn't correct and I don't understand why it is being received like this, any help is greatly appreciated! See below for the VB.NET code.
Class:
Public Class JSON_get_sensor_id_POST
Public Property tester_id() As Integer
Get
Return m_tester_id
End Get
Set(ByVal value As Integer)
m_tester_id = value
End Set
End Property
Private m_tester_id As Integer
Public Property operation() As String
Get
Return m_operation
End Get
Set(ByVal value As String)
m_operation = value
End Set
End Property
Private m_operation As String
End Class
Call function:
Dim set_tester_id As Integer = 1
Dim set_operation As String = "P"
Dim manuf_url As String = "https://XYZ...."
Dim JSON_to_send As New JSON_get_sensor_id_POST
JSON_to_send.tester_id = set_tester_id
JSON_to_send.operation = set_operation
Dim postData = JsonConvert.SerializeObject(JSON_to_send, Formatting.Indented)
Dim return_object = POST_to_Server(manuf_url, postData)
Upload Function:
Private Function POST_to_Server(ByVal post_url As String, ByVal JSON_to_post As Object)
Dim user_login As String = "blah#blah.com"
Dim user_pass As String = "blah"
Dim myCache As New CredentialCache()
myCache.Add(New Uri(post_url), "Basic", New NetworkCredential(user_login, user_pass))
' Create a request using a URL that can receive a post.
Dim request As WebRequest = WebRequest.Create(post_url)
' Set the Method property of the request to POST.
request.Credentials = myCache
request.Method = "POST"
request.ContentType = "application/json"
' Create POST data and convert it to a byte array.
Dim byteArray As Byte() = Encoding.Default.GetBytes(JSON_to_post)
' Set the ContentLength property of the WebRequest.
request.ContentLength = byteArray.Length
' Get the request stream.
Dim dataStream As 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 WebResponse = request.GetResponse()
' Display the status.
Console.WriteLine(CType(response, HttpWebResponse).StatusDescription)
' 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 StreamReader(dataStream)
' Read the content.
Dim responseFromServer As String = reader.ReadToEnd()
' Display the content.
DebugMessage(responseFromServer)
' Clean up the streams.
reader.Close()
dataStream.Close()
response.Close()
Dim myObject = JsonConvert.DeserializeObject(Of JSON_sensor_id_request_return)(responseFromServer)
Return myObject
End Function
\r and \n are escape sequences that are not visible when a string is displayed. Instead of formatting your data like this:
{
"tester_id": 2,
"operation": "P"
}
try formatting it something like this:
{"tester_id": 2,"operation": "p"}

Issues with JSON deserialization

I know there are a lot of answers related to this, however, I am unable to parse the response.
This is my JSON that I get back from wrGETURL.OpenRead(sURL):
{
"sessionKey": "TFtG+pGZ0cl0TuUbItWGy9xb9RyoPKGlY2EUF/nHe"
}
This is my JSON that I get back from getcall.OpenRead(sURL):
{
"success": true,
"message": "OK",
"total": 1,
"data": [
{
"domain": "emailsecautomate.co",
"status": "Active",
"order_date": "2017-04-26",
"service": "Email Security",
"company_name": "some name",
"address1": "1 somewhere",
"address2": null,
"city": "somecity",
"state": null,
"country": "some country",
"post_code": null,
"telephone": null,
"email": null,
"po_number": null,
"licenses": "10"
}
]
}
If I comment out the line JsonConvert.DeserializeObject(Of TotalResponse)(st) and output st to a MessageBox this is my JSON:
As you can see it's fine. However if I comment back in that line I get the following error:
401 Unauthorized
This is my full code:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
user = username.Text
pwd = password.Text
'MessageBox.Show(savedUser)
If savedUser IsNot Nothing AndAlso savedUser = "-9999" Then
Dim sqlStatement As String = "INSERT INTO my_table VALUES ('" & user & "','" & pwd & "')"
mobjHost.SetSQL(sqlStatement)
End If
Dim encoded As String = System.Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(user + ":" + pwd))
Dim sURL As String
sURL = "https://xxx.xxx/partners/auth"
Dim wrGETURL As New WebClient()
wrGETURL.Headers.Add("Authorization", "Basic " + encoded)
Try
Dim data As Stream = wrGETURL.OpenRead(sURL)
Dim reader As New StreamReader(data)
Dim s As String = reader.ReadToEnd()
Dim jsonResult = JsonConvert.DeserializeObject(Of IDictionary)(s)
'This line with/without ToString gives the error "objectreference is not set to an instance of Object"
Dim sessionKey = jsonResult.Item("sessionKey").ToString
'Not calling the function for now As even session key gives the same issue
'MessageBox.Show(sessionKey) This shows the sessionKey and everything is fine if this is used
'Me.getCustomers(sessionKey)
wrGETURL.Dispose()
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
Public Function getCustomers(ByVal sKey As String)
Dim st As String = ""
Dim getcall As New WebClient()
getcall.Headers.Add("USER", user)
getcall.Headers.Add("KEY", sKey)
getcall.Headers.Add("Content-Type", "application/json")
Dim sURL = "https://xxx.xxx/partners/customers"
Try
Dim data As Stream = getcall.OpenRead(sURL)
Dim reader As New StreamReader(data)
st = reader.ReadToEnd()
theResponse = JsonConvert.DeserializeObject(Of TotalResponse)(st)
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
Return True
End Function
These are my classes for the JSON response:
Public Class TotalResponse
Public success As String
Public message As String
Public total As String
Public data As List(Of CustomerInfo)
End Class
Public Class CustomerInfo
Public domain As String
Public status As String
Public order_date As String
Public service As String
Public company_name As String
Public address1 As String
Public address2 As String
Public city As String
Public state As String
Public country As String
Public post_code As String
Public telephone As String
Public email As String
Public po_number As String
Public licenses As String
End Class
I would consider implementing Using for your WebClient and StreamReader objects:
Managed resources are disposed of by the .NET Framework garbage collector (GC) without any extra coding on your part. You do not need a Using block for managed resources. However, you can still use a Using block to force the disposal of a managed resource instead of waiting for the garbage collector.
Please also look at turning Option Strict On which will help you write better code:
Restricts implicit data type conversions to only widening conversions, disallows late binding, and disallows implicit typing that results in an Object type.
I would also look at using the JsonSerializationException within your Catch rather than a general Exception.
With your method getCustomers, consider changing it into a function and returning TotalResponse.
Lastly consider only declaring variables if they are needed and only when they are required. This helps with reducing the amount of code and with the workflow of your code. This can be particular useful for debugging.
With these changes your code would look something like this:
Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim sessionKey As String = ""
Using wb As New WebClient()
Dim encoded As String = System.Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(user + ":" + pwd))
wb.Headers.Add("Authorization", "Basic " + encoded)
Dim data As Stream = wb.OpenRead("https://xxx.xxx/partners/auth")
Using reader As New StreamReader(data)
Try
Dim result As IDictionary = JsonConvert.DeserializeObject(Of IDictionary)(Await reader.ReadToEndAsync())
sessionKey = result.Item("sessionKey").ToString()
Catch ex As JsonSerializationException
'handle
End Try
End Using
End Using
If Not sessionKey = "" Then
Dim theResponse As TotalResponse = getCustomers(sessionKey)
End If
End Sub
Private Async Function getCustomers(ByVal sKey As String) As TotalResponse
Dim returnResponse As New TotalResponse
Using wb As New WebClient()
wb.Headers.Add("USER", user)
wb.Headers.Add("KEY", sKey)
wb.Headers.Add("Content-Type", "application/json")
Dim data As Stream = wb.OpenRead("https://api-dev.theemaillaundry.net/partners/customers")
Using reader As New StreamReader(data)
Try
returnResponse = JsonConvert.DeserializeObject(Of TotalResponse)(reader.ReadToEndAsync())
Catch ex As JsonSerializationException
'handle
End Try
End Using
End Using
Return returnResponse
End Function
I've also noted your SQL is open to SQL injection. It's outside the scope of this question however consider using SQL parameters. I'm not familiar with mobjHost.SetSQL so unfortunately I can't advise in this area.

Writing and Reading JSON in VB.net using Newtonsoft

This is my first time using JSON and I'm stuck. I'm trying to send a test SMS via http://sms.roamtech.com/smsapi/. The format is:
Send message format(json).
{
"result":{
"account":"xxxx",
"user":"xxxx",
"password":"xxxxxxxx",
"requestType":"BULK",
"alphanumeric":"xxxxxxxx",
"data":{
"linkid":"xxxxxxx",
"msisdn":"xxxxxxxxxxx",
"networkid":"1",
"message":"xxxxxxxxxxxx",
"callback":"http//test"
}
}
}
So, this is what I've come up with after reviewing various posts on this and other sites:
Imports Newtonsoft.Json
Imports Newtonsoft.Json.Linq
Imports System.IO
Imports System.Net
Imports System.Text
Module modJSON
Public Class clsResult
Public account As String
Public user As String
Public password As String
Public requestType As String
Public alphanumeric As String
Public data As New clsData
End Class
Public Class clsData
Public linkid As String
Public msisdn As String
Public networkid As String
Public message As String
Public callback As String
End Class
Public Class clsPOST
Public result As New clsResult
End Class
Public Sub chkJSON()
Dim r As New clsResult
Dim d As New clsData
Dim x As New clsPOST
r.account = "8852"
r.user = "username"
r.password = "password"
r.requestType = "BULK"
r.alphanumeric = "SMSLEO"
d.linkid = "1001"
d.msisdn = "2547xxxxxxxx"
d.networkid = "1"
d.message = "Just a test"
d.callback = "http://infiniti-africa.com/json"
r.data = d
x.result = r
Dim uriRoam As New Uri("http://sms.roamtech.com/smsapi")
Dim strJSON = JsonConvert.SerializeObject(x, Formatting.Indented)
Dim bytJSON = Encoding.UTF8.GetBytes(strJSON)
Dim result_post = SendRequest(uriRoam, bytJSON, "application/json", "POST")
MsgBox(result_post)
End Sub
Private Function SendRequest(uri As Uri, jsonDataBytes As Byte(), contentType As String, method As String) As String
Dim req As WebRequest = WebRequest.Create(uri)
req.ContentType = contentType
req.Method = method
req.ContentLength = jsonDataBytes.Length
Dim stream = req.GetRequestStream()
stream.Write(jsonDataBytes, 0, jsonDataBytes.Length)
stream.Close()
Dim response = req.GetResponse().GetResponseStream()
Dim reader As New StreamReader(response)
Dim res = reader.ReadToEnd()
reader.Close()
response.Close()
Return res
End Function
End Module
The string strJSONseems to contain the correct key:value combinations. However, the code doesn't send the test SMS and I don't get any response. 'SendRequest' returns an empty string.
Also, I'm not sure what to use for the "callback" url, which is where the delivery report is forwarded.
Note:
1. "linkid" is a unique message ID
2. "msidn" is the recipient phone number
Any help is appreciated.
I have also tried using the following class:
Public Class JsonPost
Private urlToPost As String = ""
Public Sub New(ByVal urlToPost As String)
Me.urlToPost = urlToPost
End Sub
Public Function postData(pstData As Byte()) As Boolean
Dim webClient As New WebClient()
Dim resByte As Byte()
Dim resString As String
Try
webClient.Headers("content-type") = "application/json"
resByte = webClient.UploadData(Me.urlToPost, "post", pstData)
resString = Encoding.Default.GetString(resByte)
Console.WriteLine(resString)
webClient.Dispose()
Return True
Catch ex As Exception
Console.WriteLine(ex.Message)
End Try
Return False
End Function
End Class
Then calling:
Dim strJSON = JsonConvert.SerializeObject(x)
Dim bytJSON = Encoding.UTF8.GetBytes(strJSON)
Dim jsonPost As New JsonPost("http://sms.roamtech.com/smsapi")
jsonPost.postData(bytJSON)
I'm still getting nothing. Been struggling with this for three days now. Any ideas anyone?
Turns out I've been stressing for four days over a trailing slash (/). The API URL is:
http://sms.roamtech.com/smsapi/
While I've been using:
http://sms.roamtech.com/smsapi
Lesson learnt.

Error While serializing object to json format using JsonConvert.SerializeObject function

I have a method to serialize object to json format. the object contains nested objects and lists. but i face this error :
Error getting value from 'Length' on 'Microsoft.VisualStudio.Web.PageInspector.Runtime.Tracing.ArteryFilter'.
Dim serilaize As New JsonSerializerSettings()
With serilaize
.PreserveReferencesHandling = PreserveReferencesHandling.Objects
End With
Dim strProgram As String = JsonConvert.SerializeObject(ProgramObject, Formatting.Indented, serilaize)
Any help please !
Thanks
This works:
Module Module1
Sub Main()
Dim ProgramObject = New TestObject()
ProgramObject.Items = New List(Of String)
ProgramObject.Items.Add("testitem")
Dim serialize As New Newtonsoft.Json.JsonSerializerSettings()
With serialize.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects
Dim strProgram As String = Newtonsoft.Json.JsonConvert.SerializeObject(ProgramObject, Newtonsoft.Json.Formatting.Indented, serialize)
End With
End Sub
End Module
TestObject looks like this:
Public Class TestObject
Property Items As List(Of String)
End Class