Deserialize Nested JSON in VB.NET for conversion - json

I have recently started a project using vb.net and I'm struggling to figure out how get the data for several of the items in the Mid class, o,h,l,c converted to double and loaded into an array, to eventually perform some math functions on them. Below is a small (3 candles out of 1000) sample of the JSON data I wish to work with.
{
"instrument": "EUR_USD",
"granularity": "M1",
"candles": [
{
"complete": true,
"volume": 18,
"time": "2017-07-21T04:13:00.000000000Z",
"mid": {
"o": "1.16281",
"h": "1.16284",
"l": "1.16274",
"c": "1.16281"
}
},
{
"complete": true,
"volume": 96,
"time": "2017-07-21T20:58:00.000000000Z",
"mid": {
"o": "1.16640",
"h": "1.16642",
"l": "1.16628",
"c": "1.16628"
}
},
{
"complete": true,
"volume": 32,
"time": "2017-07-21T20:59:00.000000000Z",
"mid": {
"o": "1.16628",
"h": "1.16652",
"l": "1.16628",
"c": "1.16641"
}
}
]
}
Here is the relevant code:
Imports Newtonsoft.Json
Public Class Rootobject
Public Property instrument As String
Public Property granularity As String
Public Property candles() As List(Of Candle)
End Class
Public Class Candle
Public Property complete As Boolean
Public Property volume As Integer
Public Property time As String
Public Property mid As Mid
End Class
Public Class Mid
Public Property o As String
Public Property h As String
Public Property l As String
Public Property c As String
End Class
... 'jsonstring loaded with data here
Dim obj = JsonConvert.DeserializeObject(Of Rootobject)(jsonstring)
I have attempted to do something similar to below with a loop only to receive errors.
Dim obj2 = obj.candles(0).mid.o
I have also tried to find ways of using JObject.Parse(jsonstring) without any success. So, specifically what is the best way to get the values in the Mid class each loaded into an array for further processing?
Thanks in advance.

If you want to get all the Mid objects into an array, you can use Linq to project them from the collection.
Dim mids As Mid() = obj.candles.Select(Function(candle) candle.mid).ToArray()
If you want a collection of a specific Mid property just select the one you want
Dim os As Double() = obj.candles.Select(Function(candle) Double.Parse(candle.mid.o)).ToArray()
or grab it from the mids array project before
Dim os As Double() = mids.Select(Function(mid) Double.Parse(mid.o)).ToArray()
The same can be done for any of the other properties with mid

Related

Serialize datatable with bindingsource to Json

I have a REST API from which I get the JSON data back.
The JSON model looks like the following:
{
"Id": "",
"Name": "",
"ExternalId": "",
"Headers": [
{
"Name": "",
"DisplayAt": ""
}
],
"Rows": [
"Array[string]"
],
"NewRows": [
"Array[string]"
],
"DeletedRows": [
"Array[string]"
],
"CompanyId": 0,
"IntegrationKey": ""
}
I've made a Class model that looks like the following:
Imports Newtonsoft.Json
Namespace Models
Public Class Header
<JsonProperty("Name")>
Public Property Name As String
<JsonProperty("DisplayAt")>
Public Property DisplayAt As String
End Class
Public Class DataSource
<JsonProperty("Id")>
Public Property Id As String
<JsonProperty("Name")>
Public Property Name As String
<JsonProperty("Headers")>
Public Property Headers As Header()
<JsonProperty("Rows")>
Public Property Rows As String()()
<JsonProperty("TotalRows")>
Public Property TotalRows As Integer
<JsonProperty("LastUpdated")>
Public Property LastUpdated As DateTime
<JsonProperty("CompanyId")>
Public Property CompanyId As Integer
End Class
Public Class Category
<JsonProperty("DataSource")>
Public Property DataSource As DataSource
End Class
End Namespace
From the array rows I retrieve all my necessary data which is saved in a datatable. Via a BindingSource all the fields are bound to the listbox and all changes are saved to the datatable.
The JSON is deserialized with NewtonSoft.
Now I want to save the changes back to the database via a PUT statement. Therefore I have to serialize the datatable.
I can do that with the following code:
json = JsonConvert.SerializeObject(datatable, Formatting.Indented)
In this case I'm getting only the array from the Rows in a nice JSON format.
My first question is:
How do I serialize the datatable so that I can also pass the ID and externalID in my JSON?
My second question:
Does it updates all the datarows from the database or is it also possible to just update the changed rows?

How to Read Json Response In vb.net

I want to read a data from Json Response But i am getting Difficulty to get the data.
i want to read this item from Json Response as Shown Below
period, fromDate, dueDate, totalInstallmentAmountForPeriod
Json Response
{
"currency": {
"decimalPlaces": 0,
"inMultiplesOf": 1
},
"loanTermInDays": 92,
"totalPrincipalDisbursed": 100000,
"periods": [
{
"dueDate": [
2022,
7,
8
],
"principalDisbursed": 100000,
"totalActualCostOfLoanForPeriod": 0
},
{
"period": 1,
"fromDate": [
2022,
7,
8
],
"dueDate": [
2022,
8,
8
],
"daysInPeriod": 31,
"totalInstallmentAmountForPeriod": 36035
},
{
"period": 2,
"fromDate": [
2022,
8,
8
],
"dueDate": [
2022,
9,
8
],
"daysInPeriod": 31,
"totalInstallmentAmountForPeriod": 36035
}
],
"mandatorySavings": [
{ "periodId": 0"expectedSavings": 10000.000}]
}
Your JSON is invalid, it looks like there is a missing comma after mandatorySavings -> periodId and expectedSavings.
Visual Studio has a cool feature called Paste JSON as Classes that can be found under Edit > Paste Special > Paste JSON as Classes. Using either Newtonsoft.Json or System.Text.Json, you can tidy the classes up a little bit using decorators so that you can conform to .NET standard naming conventions while still serializing the JSON to the expected values. I also prefer to use IEnumerables over arrays, but the paste JSON as classes uses the latter.
This is how the class definitions would look tidied up a bit:
Public Class Rootobject
<JsonProperty("currency")>
Public Property Currency As Currency
<JsonProperty("loanTermInDays")>
Public Property LoanTermInDays As Integer
<JsonProperty("totalPrincipalDisbursed")>
Public Property TotalPrincipalDisbursed As Integer
<JsonProperty("periods")>
Public Property Periods As IEnumerable(Of Period)
<JsonProperty("mandatorySavings")>
Public Property MandatorySavings As IEnumerable(Of Mandatorysaving)
End Class
Public Class Currency
<JsonProperty("decimalPlaces")>
Public Property DecimalPlaces As Integer
<JsonProperty("inMultiplesOf")>
Public Property InMultiplesOf As Integer
End Class
Public Class Period
<JsonProperty("dueDate")>
Public Property DueDate As IEnumerable(Of Integer)
<JsonProperty("principalDisbursed")>
Public Property PrincipalDisbursed As Integer
<JsonProperty("totalActualCostOfLoanForPeriod")>
Public Property TotalActualCostOfLoanForPeriod As Integer
<JsonProperty("period")>
Public Property Period As Integer
<JsonProperty("fromDate")>
Public Property FromDate As IEnumerable(Of Integer)
<JsonProperty("daysInPeriod")>
Public Property DaysInPeriod As Integer
<JsonProperty("totalInstallmentAmountForPeriod")>
Public Property TotalInstallmentAmountForPeriod As Integer
End Class
Public Class Mandatorysaving
<JsonProperty("periodId")>
Public Property PeriodId As Integer
<JsonProperty("expectedSavings")>
Public Property ExpectedSavings As Integer
End Class
Now all you would need to do is use JsonConvert.DeserializeObject to convert the JSON literal to an instance of your Rootobject class:
Dim conversion = JsonConvert.DeserializeObject(Of Rootobject)(literal)
Fiddle: https://dotnetfiddle.net/Eq88rV

How to extract a specific object from a JSON?

I would like to know how to extract a specific object from a JSON.
I saw most of the problem solved on Stackoverflow before posting this, but there is no one who already talked about this.
I want need to get the slug value from the JSON objects.
Here is my code Get Users From JSON
Imports System
Imports Newtonsoft.Json.Linq
Public Module Module1
Public Sub Main()
Dim myJsonString = New System.IO.StreamReader(New System.Net.WebClient().
OpenRead("https://pastebin.com/raw/z4GZFuF3")).ReadToEnd()
Dim myJObject = JObject.Parse(myJsonString)
For Each match In myJObject("matches")
Console.WriteLine(match("id")("slug"))
Next
End Sub
End Module
And Here is the Output:
Run-time exception (line -1): Error reading JObject from JsonReader.
Current JsonReader item is not an object: StartArray. Path '', line 1, position 1.
Stack Trace:
[Newtonsoft.Json.JsonReaderException: Error reading JObject from JsonReader.
Current JsonReader item is not an object: StartArray. Path '', line 1, position 1.]
at Newtonsoft.Json.Linq.JObject.Load(JsonReader reader, JsonLoadSettings settings)
at Newtonsoft.Json.Linq.JObject.Parse(String json, JsonLoadSettings settings)
at Newtonsoft.Json.Linq.JObject.Parse(String json)
at Module1.Main()
What I have reduced since this error is that the object "matches" does not exist in the JSON text, but I have no idea what I should specify in its place to make this work.
The JSON that can be retrieved from the provided address:
(http://www.stginternational.org/wp-json/wp/v2/users)
is an array of Objects.
It can be parsed using JArray.Parse(), but I suggest to deserialize this JSON as .Net classes: it's much easier to handle.
The JSON's base object (each object in the array) is defined like this:
{
"id": 1,
"name": "drall",
"url": "",
"description": "",
"link": "http://www.stginternational.org/author/drall/",
"slug": "drall",
"avatar_urls": {
"24": "http://1.gravatar.com/avatar/dc6dd0ef71784957b629e124f19364cb?s=24&d=mm&r=g",
"48": "http://1.gravatar.com/avatar/dc6dd0ef71784957b629e124f19364cb?s=48&d=mm&r=g",
"96": "http://1.gravatar.com/avatar/dc6dd0ef71784957b629e124f19364cb?s=96&d=mm&r=g"
},
"meta": [],
"_links": {
"self": [
{
"href": "http://www.stginternational.org/wp-json/wp/v2/users/1"
}
],
"collection": [
{
"href": "http://www.stginternational.org/wp-json/wp/v2/users"
}
]
}
}
It can be represented by these .Net classes:
Public Class UserObject
Public Property Id As Long
Public Property Name As String
Public Property Url As String
Public Property Description As String
Public Property Link As Uri
Public Property Slug As String
<JsonProperty("avatar_urls")>
Public Property AvatarUrls As Dictionary(Of String, Uri)
Public Property Meta As List(Of Object)
<JsonProperty("_links")>
Public Property Links As Links
End Class
Public Class Links
Public Property Self As List(Of LinkCollection)
Public Property Collection As List(Of LinkCollection)
End Class
Public Class LinkCollection
Public property Href As Uri
End Class
With this model, you can simply use JsonConvert.DeserializeObject(), specifying the Type to deserialize to.
As mentioned, this is an Array or List of objects, where the base object is an UserObject, so you can specify a List(Of UserObject) :
Dim json = JsonConvert.DeserializeObject(Of List(Of UserObject))(json)
You can then access the class object as usual:
Imports System.Net
Imports Newtonsoft.Json
Dim users As List(Of UserObject) = Nothing
Using client As New WebClient()
Dim json = client.DownloadString([The URL])
users = JsonConvert.DeserializeObject(Of List(Of UserObject))(json)
End Using
If users IsNot Nothing Then
For Each user In users
Console.WriteLine(user.Slug)
Console.WriteLine(user.Links.Self(0).Href)
Console.WriteLine(user.Links.Collection(0).Href)
For Each avatar In user.AvatarUrls
Console.WriteLine($"Key: {avatar.Key}, Value: {avatar.Value}")
Next
Next
End If
In case you just want one of the properties (slug, in this case), you can use JArray.Parse() to parse the JSON and read the property value directly:
Using client As New WebClient()
Dim json = client.DownloadString([The URL])
Dim users = JArray.Parse(json)
For Each user As JToken In users
Console.WriteLine(user("slug"))
Next
End Using
While Jimi's answer is preferable because it deserializes the JSON into a strongly typed object, here is an alternative since you only care about getting a single property from the array of objects.
It does the following three steps:
Get the JSON from the endpoint
Convert the JSON literal into JArray
Use LINQ to get just the Slug item of each object in the array
Dim myJsonString = New System.IO.StreamReader(New System.Net.WebClient().OpenRead("http://www.stginternational.org/wp-json/wp/v2/users")).ReadToEnd
Dim arrayOfObjects = JArray.Parse(myJsonString)
Dim arrayOfSlugs = From jsonObject In arrayOfObjects Select jsonObject.Item("slug")
Example: Live Demo

vb.net Serializing Collections unable to add a collection to object?

I'm trying to generate some JSON that looks like this:
{
"#type": "MessageCard",
"sections": [
{
"activityTitle": " Request",
"facts": [
{
"name": "name1",
"value": "Value"
},
{
"name": " Date:",
"value": "Value Date"
}
],
"text": "Some Test."
}
],
"potentialAction": [
{
"#type": "ActionCard",
"name": "Add a comment",
"inputs": [
{
"#type": "TextInput",
"id": "comment",
"isMultiline": true
}
]
}
]
}
I performed a paste special into VS and it generated the class structure for me as such:
Public Class MessageCard
Public Property type As String
Public Property context As String
Public Property summary As String
Public Property themeColor As String
Public Property sections() As Section
Public Property potentialAction() As Potentialaction
End Class
I'm trying to add the sections to the object as such:
Dim m as New MessageCard
Dim s As New List(Of Section)
s.Add(s1)
s.Add(s2)
m.sections = s
The compiler complains that it cannot convert a list of Sections into a Section. Did the class get generated incorrectly, or am i constructing it incorrectly?
First, your JSON is not quite complete and the Classes you show wont create that JSON.
As posted, that JSON simply shows a Sections and potentialAction class which are not related in any way. An enclosing [ ... ] is needed to represent the MessageCard class containing the two of them.
[{
"#type": "MessageCard",
...
}]
Next, the class you have shows all sorts of things not present in the JSON: context, summary and themeColor for instance. I assume those might be missing for brevity, but it is confusing. There is also 2 other Types missing which are in the JSON, Fact and Input.
Corrected, the classes should be:
Public Class MsgCard
<JsonProperty("#type")>
Public Property ItemType As String
Public Property sections As List(Of Section)
Public Property potentialAction As List(Of Potentialaction)
Public Sub New()
sections = New List(Of Section)
potentialAction = New List(Of Potentialaction)
End Sub
End Class
Public Class Section
Public Property activityTitle As String
Public Property facts As Fact()
Public Property text As String
End Class
Public Class Fact
Public Property name As String
Public Property value As String
End Class
Public Class Potentialaction
<JsonProperty("#type")>
Public Property ActionType As String
Public Property name As String
Public Property inputs As Input()
End Class
Public Class Input
<JsonProperty("#type")>
Public Property InputType As String
Public Property id As String
Public Property isMultiline As Boolean
End Class
Notes
You did not specify a JSON serializer, so this is prepared to JSON.NET as recommended by Microsoft.
#type is an illegal property name, so the JsonProperty attribute is used to create an alias. I also used less confusingly redundant names.
You may want to change Fact and Input to List(Of T) if you will be creating and pushing them into the class object as well.
Finally, for the actual question you asked, most of the automatic class generators have trouble with arrays (even VS).
Public Property sections() As Section
' should be:
Public Property sections As Section()
That simply declares that sections will be an array, it does not create the array. Normally this is not a problem because the Serializer/Deserializer will create the array. To allow code external to the class to add to them, you probably want to use a List as the classes above do, then create the instance in the constructor:
Public Sub New()
sections = New List(Of Section)
potentialAction = New List(Of Potentialaction)
End Sub

JSON string to VB.net Object with nested list

I've got some JSON coming from a webservice looks like this:
{
"disclaimer": "Exchange r..",
"license": "Data sourced from variou..",
"timestamp": 1262365200,
"base": "USD",
"rates": {
"AED": 3.67275,
"AFN": 48.550089,
"ALL": 96.435505,
"AMD": 377.894224,
"ANG": 1.791,
"AOA": 89.174867,
"ARS": 3.79928
}
}
I've built a little class to accept it.
Class currencyValues
Class ratePairs
Property currencyCode
Property currencyValue
End Class
Property disclaimer
Property license
Property timestamp
Property base
Property rates As New List(Of ratePairs)
End Class
When I run the code to accept the JSON into the class it takes the top level properties, but the list of ratePairs does not populate.
Dim js As New System.Web.Script.Serialization.JavaScriptSerializer()
Dim recs = js.Deserialize(Of currencyValues)(curRecordJSON)
The count of list recs.Rates is zero.
What am I doing wrong?
The rates property in the original json is not an array, and therefore can't be deserialised to a list.
It is in fact an object, with properties such as AED and AFN etc. You are able to deserialise it as a Dictionary(Of String, Double), or if the properties never change, you could build a class to hold it:
Class Rates
Property AED
Property AFN
'etc
End Class