Accessing an item inside an array - json

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

Related

Serialize nested JSON string using a datatable

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)

how to filter a specific part of a json string

ive been working on json for about 2 days and its all new to me so im learning as i go i have this string im working with
{
"elements": [{
"id": "123",
"hidden": false,
"name": "testname",
"sku": "1234",
"price": 2499,
"priceType": "FIXED",
"defaultTaxRates": true,
"cost": 1299,
"isRevenue": true,
"stockCount": 0,
"itemStock": {
"item": {
"id": "123"
},
"stockCount": 3,
"quantity": 3.0
},
"modifiedTime": 1504112254000
}],
"href": "http://api.server.com/items"
}
i am usnig the Newtonsoft.Json library
Imports Newtonsoft.Json
Imports Newtonsoft.Json.Linq
Imports System.Net
Imports System.IO
Public Class Form1
Dim token = ""
Dim url = "https://api.Server.com/"
Dim mid = ""
Dim parm1 = ""
Dim parm2 = ""
Dim parm3 = ""
Dim parm = parm1 & parm2 & parm3
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim jsonURL As String = url & mid & "/items?" & parm
Dim reader As StreamReader
Dim errorMsg As String = Nothing
Try
Dim request As HttpWebRequest = CType(WebRequest.Create(jsonURL), HttpWebRequest)
request.Headers.Add("Authorization", "Bearer " + token)
Dim response As HttpWebResponse = CType(request.GetResponse(), HttpWebResponse)
reader = New StreamReader(response.GetResponseStream())
Dim jsonStr As String = reader.ReadToEnd()
Dim JsonObject As JObject = JObject.Parse(jsonStr)
Dim jsonArray As JArray = JArray.Parse(JsonObject.SelectToken("elements").ToString)
For Each items As JObject In jsonArray
Dim product As item = JsonConvert.DeserializeObject(Of item)(items.ToString)
idTxtbox.Text = product.id
hiddenTxtbox.Text = product.hidden
nameTxtbox.Text = product.name
skuTxtbox.Text = product.sku
priceTxtbox.Text = product.price
priceTypeTxtbox.Text = product.priceType
defaultTaxRatesTxtbox.Text = product.defaultTaxRates
CostTxtbox.Text = product.cost
isRevenueTxtbox.Text = product.isRevenue
stockCountTxtbox.Text = product.stockCount
For Each itema In product.itemStock
ListBox1.Items.Add(itema("itemStock"))
Next
modifiedTimeTxtbox.Text = product.modifiedTime
MsgBox("")
Next
Catch ex As WebException
errorMsg = "Download failed. The response from the server was: " +
CType(ex.Response, HttpWebResponse).StatusDescription
Console.WriteLine("Error: " + errorMsg)
End Try
End Sub
End Class
Class item
Public id As String
Public hidden As String
Public name As String
Public sku As String
Public price As String
Public priceType As String
Public defaultTaxRates As String
Public cost As String
Public isRevenue As String
Public stockCount As String
'Public itemStock As Dictionary(Of String, String) = New Dictionary(Of String, String)
'Public itemStock As List(Of String) = New List(Of String)
Public Property itemStock() As IList(Of String)
Get
Return m_itemStock
End Get
Set(ByVal value As IList(Of String))
m_itemStock = value
End Set
End Property
Private m_itemStock As IList(Of String)
Public modifiedTime As String
End Class
i can get all the values of the first group of data but cant seems the "stockCount": 3 to show up any idea how i can phrase this?
sorry if im not super clear if you need more info i will try to provide it
i have updated the code of what i have so far i have gotten the JsonConvert.DeserializeObject to work but still cant seem to get the values of
"itemStock": {
"item": {
"id": "123"
},
"stockCount": 3,
"quantity": 3.0
},
to populate in listbox1.items
i receive this error
Cannot deserialize the current JSON object (e.g. {"name":"value"})
into type 'System.Collections.Generic.IList`1[System.String]' because
the type requires a JSON array (e.g. [1,2,3]) to deserialize
correctly. To fix this error either change the JSON to a JSON array
(e.g. [1,2,3]) or change the deserialized type so that it is a normal
.NET type (e.g. not a primitive type like integer, not a collection
type like an array or List) that can be

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