Serialize nested JSON string using a datatable - json

I have this JSON string:
{
"DataflowID": 1234,
"Data": [
{
"Key": "TIMESTAMP",
"Value": "2019/11/11 07:00:00"
},
{
"Key": "test1",
"Value": "5.819720684"
},
{
"Key": "test2",
"Value": "12.47921946"
}
]
}
And I am using the below code to get the data from the database and make the JSON string:
Imports Newtonsoft.Json
Dim dataSet As DataSet = New DataSet("dataSet")
dataSet.[Namespace] = "NetFrameWork"
Dim jsonTable As DataTable = New DataTable()
Dim keyColumn As DataColumn = New DataColumn("Key")
Dim valueColumn As DataColumn = New DataColumn("Value")
jsonTable.Columns.Add(keyColumn)
jsonTable.Columns.Add(valueColumn)
dataSet.Tables.Add(jsonTable)
jsonTable.TableName = "Data"
For m = 1 To g
Dim dataRow2 As DataRow = jsonTable.NewRow
dataRow2("Key") = "Timestamp"
dataRow2("Value") = testTimestamp(m)
jsonTable.Rows.Add(dataRow2)
For k = 1 To tagsCounter
Dim dataRow1 As DataRow = jsonTable.NewRow
dataRow1("Key") = testName(k)
dataRow1("Value") = testValue(m, k)
jsonTable.Rows.Add(dataRow1)
Next k
Next m
But I cannot make the property dataFlowID .

I would build a class to represent the JSON and fill it in. For example:
Public Class JsonHolder
Public DataflowId As Integer
Public Data As DataTable
End Class
It looks like you already have the Data part sorted, so you just need to put that into a new instance of this holder class along with the DataflowId:
Dim holder = New JsonHolder With {
.DataflowId = 1234,
.Data = jsonTable
}
Then use Newtonsoft to serialise to JSON:
Dim json = JsonConvert.SerializeObject(holder, Formatting.Indented)

Related

Accessing an item inside an array

Please see the JSON below, which I have validated using https://jsonlint.com/:
{
"meta": {
"limit": 3,
"count": 3
},
"data": [{
"id": "1",
"MoreInformation": {
"id2": "22"
},
"type": "Person"
},
{
"id": "2",
"MoreInformation": {
"id2": "42"
},
"type": "Person"
},
{
"id": "3",
"MoreInformation": {
"id2": "99"
},
"type": "Person"
}
]
}
Please see the code below:
Module Module1
Sub Main()
Dim json As String = "{""meta"": {""limit"": 2,""count"": 2},""data"": [{""id"": ""1"",""MoreInformation"": {""id2"": ""22""},""type"": ""Person""},{""id"": ""2"",""MoreInformation"": {""id2"": ""42""},""type"": ""Person""},{""id"": ""3"",""MoreInformation"": {""id2"": ""99""},""type"": ""Person""}]}"
Dim jo As JObject = JObject.Parse(json)
Dim a As JArray = CType(jo("data"), JArray)
Dim list As New List(Of Person)
For Each item In a.Children()
Dim itemProperties = item.Children(Of JProperty)()
Dim person As New Person
person.id1 = itemProperties.FirstOrDefault(Function(x) x.Name = "id")
person.id2 = itemProperties.FirstOrDefault(Function(x) x.Name = "id2")
list.Add(person)
Next
End Sub
End Module
Public Class Person
Public Property id1
Public Property id2
End Class
I want the output to be a list of three persons.
The problem is with this line:
person.id2 = itemProperties.FirstOrDefault(Function(x) x.Name = "id2")
It always returns nothing. How can I populate person.id2 with id2 from the JSON?
Update
This works:
Sub Main()
Dim json As String = "{""meta"": {""limit"": 2,""count"": 2},""data"": [{""id"": ""1"",""MoreInformation"": {""id2"": ""22""},""type"": ""Person""},{""id"": ""2"",""MoreInformation"": {""id2"": ""42""},""type"": ""Person""},{""id"": ""3"",""MoreInformation"": {""id2"": ""99""},""type"": ""Person""}]}"
Dim jo As JObject = JObject.Parse(json)
Dim a As JArray = CType(jo("data"), JArray)
Dim list As List(Of Person) = JsonConvert.DeserializeObject(Of List(Of Person))(a.ToString)
Console.WriteLine("got here")
End Sub
providing I change the classes to this:
Public Class Person
Public Property id
Public Property MoreInformation
End Class
Public Class MoreInformation
Public Property id2
End Class
However, I am still intigured how to get the code in my original post working.
I'm not sure if this is the answer you want, but I tried like the code below.
Try
Dim json As String = "{""meta"": {""limit"": 2,""count"": 2},""data"": [{""id"": ""1"",""MoreInformation"": {""id2"": ""22""},""type"": ""Person""},{""id"": ""2"",""MoreInformation"": {""id2"": ""42""},""type"": ""Person""},{""id"": ""3"",""MoreInformation"": {""id2"": ""99""},""type"": ""Person""}]}"
Dim jo As JObject = JObject.Parse(json)
Dim a As JArray = CType(jo("data"), JArray)
Dim list As New List(Of Person)
For Each item In a.Children()
Dim itemProperties = item.Children(Of JProperty)()
Dim itemProperties2 = item.SelectToken("MoreInformation").Children(Of JProperty)()
Dim person As New Person
person.id1 = itemProperties.FirstOrDefault(Function(x) x.Name = "id")
person.id2 = itemProperties2.FirstOrDefault(Function(x) x.Name = "id2")
list.Add(person)
Next
For Each item In list
Debug.WriteLine("id1:" & item.id1.ToString & " id2:" & item.id2.ToString)
Next
Catch ex As Exception
MsgBox(ex.ToString)
End Try

Deserialize Application Insights Analytics with Json.net

I'm trying to use Json.net to deserialize JSON from Application Insights Analytics (AIA) into my class. I'm not sure if I'm approaching it right, but I use LINQ-to-JSON to get at the data section of the JSON and then try to deserialize to my class using this code:
Dim rawjson As String = GetTelemetry()
Dim o As JObject = JObject.Parse(rawjson)
Dim ds = DirectCast(o("Tables")(0)("Rows"), JArray)
Dim Sessions As List(Of Session) = JsonConvert.DeserializeObject(Of List(Of Session))(ds)
This fails as the JSON from AIA is in this format:
"Rows": [
[
"Boy",
"9",
"",
"",
"0",
"0",
"22",
"0"
],
[
"Boy",
"9",
"",
"",
"0",
"0",
"41",
"0"
],
Notice the data for the individual rows is an array rather than an object.
My Session class is defined like this:
Public Class Session
Public Property Gender As String
Public Property Age As Integer
Public Property SessionVids As Integer
Public Property TotalVids As Integer
Public Property ChildUse As Integer
Public Property ChildTime As Integer
Public Property AdultUse As Integer
Public Property AdultTime
End Class
Can someone please explain how to do this?
You can convert the JArray of rows (ds) into a list of Session objects like this:
Dim Sessions As List(Of Session) =
ds.Select(Function(ja)
Dim s As New Session()
s.Gender = ja(0).Value(Of String)()
s.Age = GetInt(ja(1))
s.SessionVids = GetInt(ja(2))
s.TotalVids = GetInt(ja(3))
s.ChildUse = GetInt(ja(4))
s.ChildTime = GetInt(ja(5))
s.AdultUse = GetInt(ja(6))
s.AdultTime = GetInt(ja(7))
Return s
End Function).ToList()
where GetInt is a helper function defined like this:
Public Function GetInt(jt As JToken) As Integer
Dim i As Integer
If Integer.TryParse(jt.Value(Of String)(), i)
Return i
End If
Return 0
End Function
The helper function is needed since the JSON has empty strings for some of the values while your class requires valid integers.
Fiddle: https://dotnetfiddle.net/GqFcov

vb.net Json Error converting value to type

I'm newbie in JSON, I made a first try with a file and it works fine. But my second file gives me headache.
The problem is that the second file start with this : [
my first file was like this
{
"GC": {
"Parameters": {
"feed": "gc",
"lang_code": "fr",
"fmt": "json",
} .................
I try many different things and I always have an error. The error is :
Additional information: Error converting value "person" to type 'JSonPerson'. Path '[0]', line 1, position 9.
Here's the second JSON file text (that start with the bracket "[" :
["person",
[{
"id": "19023",
"player_id": "16493",
"coach_id": "0",
"manager_id": "",
"official_id": ""
},
{
"id": "19024",
"player_id": "16494",
"coach_id": "1",
"manager_id": "",
"official_id": ""
}]]
Now my class:
Public Class JSonPerson
Public person As List(Of JSon_PersonDetail)
End Class
Public Class JSon_PersonDetail
Public id As String
Public player_id As String
Public coach_id As String
Public manager_id As String
Public official_id As String
Public user_id As String
Public first_name As String
Public last_name As String
End Class
And my code (that is the same for the first file, works perfect, but not with the second file):
Dim client As New WebClient()
Dim stream As Stream = client.OpenRead("c:\Global_files\person.json")
Dim reader2 As New StreamReader(stream)
Dim jsonData As String = reader2.ReadToEnd
Dim obj As List(Of JSonPerson)
obj = JsonConvert.DeserializeObject(Of List(Of JSonPerson))(jsonData)
I try this too:
Dim obj As JSonPerson
obj = JsonConvert.DeserializeObject(Of JSonPerson)(jsonData)
But I'm not able to push data inside my class I have errors:
Does someone know what's my problem ?
Update
I also tried reading directly from the stream using a JsonTextReader, like so:
Dim client As New WebClient()
Dim stream As Stream = client.OpenRead("c:Global_files\person.json")
Dim reader2 As New StreamReader(stream)
Dim jsonData As String = reader2.ReadToEnd
Dim reader As New JsonTextReader(reader2)
Dim people As JSonPeople
people = JsonSerializer.CreateDefault().Deserialize(Of JSonPeople)(reader)
reader2 have data. After the variable "reader" is empty. So the people is empty.
Here's the way I did it:
Dim client As New WebClient()
Dim stream As Stream = client.OpenRead("c:\Global_files\person.json")
Dim reader2 As New StreamReader(stream)
Dim jsonData As String = reader2.ReadToEnd
Dim jResults As JArray = JArray.Parse(jsonData)
'Here I know that is the children #1 that I need
Dim Data As List(Of JToken) = jResults.Item(1).Children().ToList
Dim vListOfPerson As New List(Of JSon_PersonDetail)
For Each item In Data
Dim ItemArray As Array = item.ToArray
Dim person As New JSon_PersonDetail
For Each element In ItemArray
Select Case element.name
Case "id"
person.id = element.value
Case "player_id"
person.player_id = element.value
Case "coach_id"
person.coach_id = element.value
Case "manager_id"
person.manager_id = element.value
Case "official_id"
person.official_id = element.value
Case "user_id"
person.user_id = element.value
Case "first_name"
person.first_name = element.value
Case "last_name"
person.last_name = element.value
End Select
Next
vListOfPerson.Add(person)
Next

VB.NET Json Parse

I'm trying to process the JSON input below. The code (bottom) throws
Error reading JObject from JsonReader.
Current JsonReader item is not an object: StartArray.
Path '', line 1, position 1.
Input:
[
{
"data": [
{
"photos": {
"data": [
{
"id": "1",
"name": "test Post",
"images": [
{
"height": 1024,
"source": "https://127.0.0.1:8080/image1.png",
"width": 1204
},
{
"height": 1204,
"source": "https://127.0.0.1:8080/image2.png",
"width": 1204
}
],
}
]
}
}
}
Code:
Dim ser As JObject = JObject.Parse(result.ToString)
Dim data As List(Of JToken) = ser.Children().ToList
Dim jsonString As String = Nothing
Dim index As Integer = 0
For Each item As JProperty In data
item.CreateReader()
Select Case item.Name
Case "data"
jsonString = item.Value.ToString
End Select
Next
ser = JObject.Parse(jsonString)
data = ser.Children().ToList
For Each item As JProperty In data
item.CreateReader()
Select Case item.Name
Case "photos"
jsonString = item.Value.ToString
End Select
Next
ser = JObject.Parse(jsonString)
data = ser.Children().ToList
For Each item As JProperty In data
item.CreateReader()
Select Case item.Name
Case "data"
For Each comment As JObject In item.Values
Dim _id As String = comment("id")
Dim _title As String = comment("title")
Dim _name As String = comment("name")
Dim _source As String = comment("source")
Dim source As List(Of JToken) = item.Value.ToList
For Each images As JProperty In source
item.CreateReader()
Select Case item.Name
Case "images"
Dim _tempsource As String = source("source")
_source += _tempsource & vbCrLf
End Select
Next
Dim _created_time As String = comment("created_time")
Dim itm As New ListViewItem(_id, 1)
itm.SubItems.Add(_title)
itm.SubItems.Add(_name)
itm.SubItems.Add(_source)
itm.SubItems.Add(_created_time)
lvItems.Items.AddRange(New ListViewItem() {itm})
index += 1
Next
End Select
Next
I access this namespace with
Imports Newtonsoft.Json
Imports Newtonsoft.Json.Linq
What am I doing wrong?
I used JSONLint to debug your JSON, because it is not valid. you must check whether your source is sending you invalid JSON, or there was a typo when posting it here. This would be valid JSON:
[{
"data": [{
"photos": {
"data": [{
"id": "1",
"name": "test Post",
"images": [{
"height": 1024,
"source": "https://127.0.0.1:8080/image1.png",
"width": 1204
}, {
"height": 1204,
"source": "https://127.0.0.1:8080/image2.png",
"width": 1204
}]
}]
}
}]
}]
Then, You can use a tool like JSON Utils or VS itself (copying JSON to the clipboard and using Edit > Paste Special > Paste JSON as Classes) to generate VB classes that match JSON structure:
Public Class Image
Public Property height As Integer
Public Property source As String
Public Property width As Integer
End Class
Public Class PhotoDatum
Public Property id As String
Public Property name As String
Public Property images As Image()
End Class
Public Class Photos
Public Property data As PhotoDatum()
End Class
Public Class Datum
Public Property photos As Photos
End Class
Public Class SER
Public Property data As Datum()
End Class
Anyway, if you add the classes above to your project, you can just do this:
Dim MySER = JsonConvert.DeserializeObject(Of SER)(jsonString)
Dim itm As ListViewItem
Dim MyItems As New List(Of ListViewItem)
For Each d In MySER
If d.photos IsNot Nothing Then
For each dd in d.photos.data
If dd.images IsNot Nothing Then
For each img In dd.images
itm = New ListViewItem(dd.id, 1)
itm.SubItems.Add(dd.name)
itm.SubItems.Add(img.source)
MyItems.Add(itm)
Next
End If
Next
End If
Next
lvItems.Items.AddRange(MyItems)
And work with your structured objects.

JSON.net VB.net parse to get only colors from json return

Hey all I am trying to parse the following JSON in order to get the colors for the exterior:
{
"styles": [{
"make": {
"id": 200001444,
.....etc etc
},
"model": {
"id": "Honda_Pilot",
.....etc etc
},
"engine": {
"id": "200058127",
.....etc etc
"rpm": {
"horsepower": 5700,
"torque": 4800
},
"valve": {
"timing": "variable valve timing",
"gear": "single overhead camshaft"
}
},
"transmission": {
"id": "200058128",
.....etc etc
},
"drivenWheels": "four wheel drive",
.....etc etc
"colors": [{
"category": "Interior",
"options": [{
"id": "200058068",
"name": "Blue",
.....etc etc
}]
}, {
"category": "Exterior",
"options": [{
"id": "200058073",
"name": "Crystal Black Pearl",
.....etc etc
}
}, {
"id": "200058072",
"name": "Polished Metal Metallic",
.....etc etc
So far I have gotten to the "colors" but I am unable to get any further:
VB.net code:
Dim json2
Using httpClient = New HttpClient()
json2 = Await httpClient.GetStringAsync("URL HERE")
End Using
Dim rootObject2 = JObject.Parse(json2)
For Each token As JToken In rootObject2("styles")
Dim results As List(Of JToken) = token.Children().ToList
For Each item As JProperty In results
Select Case item.Name
Case "colors"
For Each subitem As JObject In item.Values
Dim tmp = subitem("category")
For Each subitem2 As JObject In tmp.Values
Dim tmp2 = subitem("category")
Next
Next
End Select
Next
Next
I am sure there's a simpler way of going about this but I just wanted to show that I did try to figure it out before coming here to get help on the code.
I am trying to loop through and get all Exterior colors by name.
Thanks!
I usually use a System.Web.Script.Serialization.JsonSerializer class instance.
In a Console (Module) Application, ensure you include System.Web.Extensions as a reference to your project...
Define your Models that will be used in the Deserilization process.
VB.NET
Module Module1
Sub Main()
Dim result = GetData()
End Sub
Public Class MakeStyle
Public Property Id As Integer
End Class
Public Class ModelStyle
Public Property Id As String
End Class
Public Class EngineStyle
Public Property Id As String
Public Property RotationsPerMinute As EngineRotationsPerMinuteStyle
End Class
Public Class EngineRotationsPerMinuteStyle
Public Property HorsePower As Integer
Public Property Torque As Integer
End Class
Public Class Payload
Public Property Make As MakeStyle
Public Property Model As ModelStyle
Public Property Engine As EngineStyle
Public Property Colors As IEnumerable(Of ColorStyle)
End Class
Public Class ColorStyleOptionItem
Public Property Id As String
Public Property Name As String
End Class
Public Class ColorStyle
Public Property Category As String
Public Property Options As IEnumerable(Of ColorStyleOptionItem)
End Class
Public Class DataItem
Public Property Category As String
Public Property Id As String
Public Property Name As String
End Class
Public Function GetData() As IEnumerable(Of DataItem)
Dim payloadString As String = GetDemoData() ' json serialized data
Dim serializer As System.Web.Script.Serialization.JavaScriptSerializer = New System.Web.Script.Serialization.JavaScriptSerializer()
Dim payload = serializer.Deserialize(Of Payload)(payloadString) ' sets Property Values of Payload to 'Nothing' when the json fields are not present in the json string.
Dim data As IEnumerable(Of DataItem) = payload.Colors.SelectMany(Function(item) item.Options.Select(Function(opt) New DataItem With {.Category = item.Category, .Id = opt.Id, .Name = opt.Name}))
GetData = data
End Function
Public Function GetDemoData() As String
Dim serializer As System.Web.Script.Serialization.JavaScriptSerializer = New System.Web.Script.Serialization.JavaScriptSerializer()
GetDemoData = serializer.Serialize(New Payload() With {
.Make = New MakeStyle() With {.Id = 200001444},
.Model = New ModelStyle() With {.Id = "Honda_Pilot"},
.Engine = New EngineStyle With {.Id = "200058127", .RotationsPerMinute = New EngineRotationsPerMinuteStyle() With {.HorsePower = 5700, .Torque = 4800}},
.Colors = New ColorStyle() {
New ColorStyle() With {
.Category = "Interior",
.Options = New ColorStyleOptionItem() {
New ColorStyleOptionItem() With {.Id = "200058068", .Name = "Blue"}
}
},
New ColorStyle() With {
.Category = "Exterior",
.Options = New ColorStyleOptionItem() {
New ColorStyleOptionItem() With {.Id = "200058073", .Name = "Crystal Black Pearl"},
New ColorStyleOptionItem() With {.Id = "200058072", .Name = "Polished Metal Metallic"}
}
}
}
})
End Function
End Module
I think you want something like this:
For Each style As JToken In rootObject2("styles")
Dim model As String = style.SelectToken("model.id").ToString()
Console.WriteLine("Exterior colors for " & model & ":")
For Each colorCategory As JToken In style("colors")
Dim categoryName As String = colorCategory("category").ToString()
If categoryName = "Exterior" Then
For Each opt As JToken In colorCategory("options")
Dim color as String = opt("name").ToString()
Console.WriteLine(" " & color)
Next
End If
Next
Next
Fiddle: https://dotnetfiddle.net/IVc2EC