Trying To Deserialize JSON Dictionairy Using Objects - json

As standard, I've created a web request and receive a response as JSON format. I'm trying to deserialize this JSON using JSON.NET (I don't think I need this though).
I've tried using the following code, however I'm not entirely sure on how to make the object actually contain some data. When I run this code, I get an error message displaying that my JObject "current" is "Nothing".
Imports System.Net
Imports System.IO
Imports Newtonsoft.Json.Linq
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
ServicePointManager.Expect100Continue = True
ServicePointManager.SecurityProtocol = CType(3072, SecurityProtocolType)
ServicePointManager.DefaultConnectionLimit = 9999
Dim uriString As String = "https://dev.tescolabs.com/grocery/products/?query=chicken&offset=0&limit=2"
Dim uri As New Uri(uriString)
Dim r As HttpWebRequest = HttpWebRequest.Create(uri)
r.Headers("Ocp-Apim-Subscription-Key") = "xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
r.Method = "GET"
r.Proxy = Nothing
Dim re As HttpWebResponse = r.GetResponse()
Dim read As New StreamReader(re.GetResponseStream())
Dim raw As String = read.ReadToEnd()
Dim a As JObject = JObject.Parse(raw)
Dim current As JObject = DirectCast(a("image"), JObject)
MessageBox.Show(current("image"))
End Sub
End Class
Public Class Totals
Public Property all As Integer
Public Property _new As Integer
Public Property offer As Integer
End Class
Public Class Result
Public Property image As String
Public Property superDepartment As String
Public Property tpnb As Integer
Public Property ContentsMeasureType As String
Public Property name As String
Public Property UnitOfSale As Integer
Public Property description() As String
Public Property AverageSellingUnitWeight As Single
Public Property UnitQuantity As String
Public Property id As Integer
Public Property ContentsQuantity As Single
Public Property department As String
Public Property price As Single
Public Property unitprice As Single
End Class
So, in textbox1, should be each product, including all of the information for each product. After extracting all of this information, I would ultimately like to add the information for each product in a datagridview, to present the information in a more clear manner. However, I can't get past this stage.
I have now tried the following code:
Dim results = Newtonsoft.Json.JsonConvert.DeserializeObject(Of Result)(raw)
For Each image In results.image
TextBox1.Text = "Image URL:" + results.image
Next
JSON I receive as response:
{
"uk" : {
"ghs" : {
"products" : {
"input_query" : "chicken",
"output_query" : "chicken",
"filters" : { },
"queryPhase" : "primary",
"totals" : {
"all" : 1358,
"new" : 9,
"offer" : 478
},
"config" : "default",
"results" : [ {
"image" : "http://img.tesco.com/Groceries/pi/325/5057008546325/IDShot_90x90.jpg",
"superDepartment" : "Fresh Food",
"tpnb" : 81866107,
"ContentsMeasureType" : "G",
"name" : "Tesco British Chicken Breast Portions 650G",
"UnitOfSale" : 1,
"description" : [ "Fresh class A skinless chicken breast fillet portions."],
"AverageSellingUnitWeight" : 0.746,
"UnitQuantity" : "KG",
"id" : 294007923,
"ContentsQuantity" : 650,
"department" : "Fresh Meat & Poultry",
"price" : 3.8,
"unitprice" : 5.85
}, {
"image" : "http://img.tesco.com/Groceries/pi/531/5054775703531/IDShot_90x90.jpg",
"superDepartment" : "Fresh Food",
"tpnb" : 64083120,
"ContentsMeasureType" : "KG",
"name" : "Tesco British Large Whole Chicken 1.55-1.95Kg",
"UnitOfSale" : 1,
"AverageSellingUnitWeight" : 1.785,
"description" : [ "Fresh Class A whole chicken without giblets."],
"UnitQuantity" : "KG",
"id" : 292276232,
"ContentsQuantity" : 1.75,
"department" : "Fresh Meat & Poultry",
"price" : 3.5,
"unitprice" : 2.0
} ],
"suggestions" : [ ]
}
}
}
}
However I still don't receive the image URL in textbox1, and have no idea as to why. Any help would be greatly appreciated.

I've never used JSON.NET or NEWTONSOFT, I tend to only mess around with JSON a little, I usually just use the 'built in' method.
Your results are in an array which is what your first problem would probably have been. Then your For Each looks like it's getting on the right track but not sure results are being referenced correctly?
Anyway...
He's a working example that will hopefully help.
I just made a simple WinForm and added a button.
I added a reference to: System.Web.Extensions
Try code below: (let me know how you got on)
Imports System.Web.Script.Serialization
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'This is just my JSON source I used for testing. (The JSON response you posted)
Dim raw As String = IO.File.ReadAllText("C:\MEDIA\json_test.json")
'This should now be the same as your: Dim raw As String = read.ReadToEnd()
'From here on, try this:
'Deserialise
Dim ser As JavaScriptSerializer = New JavaScriptSerializer()
Dim Tesco As JSON = New JSON
Tesco = ser.Deserialize(Of JSON)(raw)
'Loop through results and print each image URL
For Each r As Result In Tesco.uk.ghs.products.results
Console.WriteLine("Image URL:" & r.image)
Next
End Sub
End Class
Public Class Totals
Public Property all As Integer
Public Property [new] As Integer
Public Property offer As Integer
End Class
Public Class Result
Public Property image As String
Public Property superDepartment As String
Public Property tpnb As Integer
Public Property ContentsMeasureType As String
Public Property name As String
Public Property UnitOfSale As Integer
Public Property description As String()
Public Property AverageSellingUnitWeight As Double
Public Property UnitQuantity As String
Public Property id As Integer
Public Property ContentsQuantity As Double
Public Property department As String
Public Property price As Double
Public Property unitprice As Double
End Class
Public Class Products
Public Property input_query As String
Public Property output_query As String
Public Property queryPhase As String
Public Property totals As Totals
Public Property config As String
Public Property results As Result()
Public Property suggestions As Object()
End Class
Public Class Ghs
Public Property products As Products
End Class
Public Class Uk
Public Property ghs As Ghs
End Class
Public Class JSON
Public Property uk As Uk
End Class

Related

Convert Json to Datatable when json has multiple levels

In my program, it's the first time that I'm trying to parse JSON content.
The result I'm trying to get is a DataTable with columns like this:
| Text of group | Text of Item | Command of Item |
The JSON is the following:
{
"Groups": [
{
"Items": [
{
"Command": "Framework.Windows.Components.ESScrollerForm, ESGrid|SHOW|Χρήστες|ESGOUser|ESGOUser_def|||65535",
"Key": "834888dd-c4d5-449a-96b7-67db5c3d2692",
"Text": "Users",
"ImageIndex": -1
},
{
"Command": "Framework.Windows.Components.ESScrollerForm, ESGrid|SHOW|QuestionaireSurveyorQuery|ESTMTask|QuestionaireSurveyorQuery|||0",
"Key": "b71de66d-2baf-4452-ada7-8fc67044876b",
"Text": "QuestionaireSurveyorQuery"
}
],
"Expanded": true,
"Tag": "",
"Key": "b741e67a-a3cd-4b97-91cf-ae9c9d9db7d7",
"Text": "Settings",
"ImageIndex": -1
},
{
"Items": [
{
"64String": "Soap",
"Command": "cInvoke|Booked Requests Agent Booking|SHOW|ESMIS|BookedReqAgentBook||False",
"Key": "bfbc3d4a-ef8a-49a0-918a-331813ba90fb",
"Text": "Requests Agent Booking",
"ImageIndex": -1
},
{
"64String": "Jrse",
"Command": "cInvoke|HHG SF Profit \u0026 Loss|SHOW|ESMIS|HHGFileProfitability||False",
"Key": "cf1cbffc-aba9-4e0f-8d6c-ba7219932fb6",
"Text": "HHG SF Profit \u0026\u0026 Loss",
"ImageIndex": -1
}
],
"Tag": "..CSShortcuts\\HHGReporting.ebl",
"Key": "eff0d713-a70e-4582-a103-b8cc5cecdad6",
"Text": "HHGReporting",
"ImageIndex": -1
}
]
}
In the past, I have succesfully parsed complex XML using XPATH, but now I have struggled a lot using Newtonsoft.Json with no success.
What I have tried, is to first create 3 classes using online generators:
Public Class Rootobject
Public Property Groups() As Group
End Class
Public Class Group
Public Property Items() As Item
Public Property Expanded As Boolean
Public Property Tag As String
Public Property Key As String
Public Property Text As String
Public Property ImageIndex As Integer
End Class
Public Class Item
Public Property Command As String
Public Property Key As String
Public Property Text As String
Public Property ImageIndex As Integer
Public Property 64String As String
End Class
Any ideas how the deserialized commands should be, in order the get the data as a DataTable with the structure described?
You have an almost working class model, some changes are necessary to make it work as intended.
This kind of syntax is misleading:
Public Property Groups() As Group
This is not a collection of objects, it's just a single object of Type Group.
Change all to:
Public Property Groups As Group()
'or
Public Property Groups As List(Of Group)
To convert to DataTable with a specific selection of Columns, you need to iterate the Groups collection and, for each group, iterate the Items collection, to extract the values you need.
Here, I'm using a specialized class, GroupsHandler, that contains the class Model used to deserialize a compatible JSON and to convert to DataTable partial content of the resulting data structure.
The GroupsHandler class exposes two Public methods:
Deserialize(), used to convert to .Net classes the JSON content
ToDataTable(), used to create a DataTable from the deserialized content.
You can initialize the handler and call these method as:
Dim handler = New GroupsHandler(Json)
' Only deserialize
Dim myGroups = handler.Deserialize()
' Deserialize and convert to DataTable
Dim dt = handler.ToDataTable()
The Group class name is changed in ItemsGroup, since Group is a language keyword.
The 64String property name changed in String64, since you cannot have a Property Name that begins with a number.
Imports Newtonsoft.Json
Public Class GroupsHandler
Private root As GroupsRoot = Nothing
Private m_json As String = String.Empty
Public Sub New(json As String)
m_json = json
End Sub
Public Function Deserialize() As List(Of ItemsGroup)
root = JsonConvert.DeserializeObject(Of GroupsRoot)(m_json)
Return root.Groups
End Function
Public Function ToDataTable() As DataTable
If root Is Nothing Then
If String.IsNullOrEmpty(m_json) Then Return Nothing
Deserialize()
End If
Dim dt As New DataTable("Groups")
dt.Columns.AddRange(New DataColumn() {
New DataColumn("GroupText", GetType(String)),
New DataColumn("ItemText", GetType(String)),
New DataColumn("ItemCommand", GetType(String))
})
For Each grp In root.Groups
For Each item In grp.Items
dt.Rows.Add(New Object() {grp.Text, item.Text, item.Command})
Next
Next
Return dt
End Function
Public Class GroupsRoot
Public Property Groups As List(Of ItemsGroup)
End Class
Public Class ItemsGroup
Public Property Items As List(Of Item)
<JsonProperty("Expanded", NullValueHandling:=NullValueHandling.Ignore)>
Public Property Expanded As Boolean?
Public Property Tag As String
Public Property Key As Guid
Public Property Text As String
Public Property ImageIndex As Long
End Class
Public Class Item
Public Property Command As String
Public Property Key As Guid
Public Property Text As String
<JsonProperty("ImageIndex", NullValueHandling:=NullValueHandling.Ignore)>
Public Property ImageIndex As Long?
<JsonProperty("64String", NullValueHandling:=NullValueHandling.Ignore)>
Public Property String64 As String
End Class
End Class

Read REST API JSON reply

I have been searching the web back an forth but couldn't find a hint to my issue.
I'm calling a REST API via RestSharp Client. I retrieve a response like this:
{
"meta": {
"query_time": 0.007360045,
"pagination": {
"offset": 1,
"limit": 100,
"total": 1
},
"powered_by": "device-api",
"trace_id": "a0d33897-5f6e-4799-bda9-c7a9b5368db7"
},
"resources": [
"1363bd6422274abe84826dabf20cb6cd"
],
"errors": []
}
I want to query the value of resources at the moment. This is the code I use:
Dim id_request = New RestRequest("/devices/queries/devices/v1?filter=" + filter, Method.GET)
id_request.AddHeader("Accept", "application/json")
id_request.AddHeader("Authorization", "bearer " + bearer)
Dim data_response = data_client.Execute(id_request)
Dim data_response_raw As String = data_response.Content
Dim raw_id As JObject = JObject.Parse(data_response_raw)
Dim id = raw_id.GetValue("resources").ToString
Unfortunately, I'm only getting ["1363bd6422274abe84826dabf20cb6cd"] as a reply instead of 1363bd6422274abe84826dabf20cb6cd
Can anyone point me into the right direction?
I have also tried to deserialize using JsonConvert.DeserializeObject() but I somehow fail.
I found this solution here but if I try to rebuild it fails as it doesn't recognize the Dictionary part
Dim tokenJson = JsonConvert.SerializeObject(tokenJsonString)
Dim jsonResult = JsonConvert.DeserializeObject(Of Dictionary(Of String, Object))(jsonString)
Dim firstItem = jsonResult.Item("data").Item(0)
EDIT:
When trying to deserialize the root as suggested but seems as if the 2nd response is nested JSON.
I have a reply like:
dr = {
"meta": {
"query_time": 0.004813129,
"powered_by": "device-api",
"trace_id": "5a355c86-37f7-416d-96c4-0c8796c940fc"
},
"resources": [
{
"device_id": "1363bd6422274abe84826dabf20cb6cd",
"policies": [
{
"policy_type": "prevention",
"policy_id": "1d34205a4e2c4d1991431c037c8e5734",
"applied": true,
"settings_hash": "7cb00a74",
"assigned_date": "2021-02-22T13:56:37.759459481Z",
"applied_date": "2021-02-22T13:57:19.962692301Z",
"rule_groups": []
}
],
"meta": {
"version": "352"
}
}
],
"errors": []
}
and I tried:
Dim restApiResponse = JsonConvert.DeserializeObject(Of RestApiResponseRoot)(dr)
' This is your array of strings
Dim resources = restApiResponse.Resources
Unfortunately I get
Newtonsoft.Json.JsonReaderException: 'Unexpected character encountered while parsing value: {. Path 'resources', line 8, position 3.'
The resources Property is an array. As usual, you need to specify which element of the array you want to consider. In this case, the first one, i.e., the element at index 0.
Dim jsonObject = JObject.Parse(data_response_raw)
Dim firstResource = jsonObject("resources")(0).ToString()
If you instead want the array content as a String array, not just the first element - assuming resources could contain more than one string (it's an array after all) - deserialize to String():
Dim jsonObject = JObject.Parse(data_response_raw)
Dim resources = JsonConvert.DeserializeObject(Of String())(jsonObject("resources").ToString())
In case you need the whole JSON response, I suggest to deserialize to a class Model that represents the JSON:
Public Class RestApiResponseRoot
Public Property Meta As Meta
Public Property Resources As List(Of String)
Public Property Errors As List(Of Object)
End Class
Public Class Meta
<JsonProperty("query_time")>
Public Property QueryTime As Double
Public Property Pagination As Pagination
<JsonProperty("powered_by")>
Public Property PoweredBy As String
<JsonProperty("trace_id")>
Public Property TraceId As Guid
End Class
Public Class Pagination
Public Property Offset As Long
Public Property Limit As Long
Public Property Total As Long
End Class
You can then deserialize the Model's Root object - the class named RestApiResponseRoot here - and access its Properties as usual:
Dim restApiResponse = JsonConvert.DeserializeObject(Of RestApiResponseRoot)(
data_response_raw
)
' This is your array of strings
Dim resources = restApiResponse.Resources
The other JSON response is slightly different, the Response Property contains an array of objects instead of string.
Some more properties and nested object are added. You just need to adjust the Model.
Public Class RestApiResponseRoot2
Public Property Meta As RootObjectMeta
Public Property Resources As List(Of Resource)
Public Property Errors As List(Of Object)
End Class
Public Class RootObjectMeta
<JsonProperty("query_time")>
Public Property QueryTime As Double
<JsonProperty("powered_by")>
Public Property PoweredBy As String
<JsonProperty("trace_id")>
Public Property TraceId As Guid
End Class
Public Class Resource
<JsonProperty("device_id")>
Public Property DeviceId As String
Public Property Policies As List(Of Policy)
Public Property Meta As ResourceMeta
End Class
Public Class ResourceMeta
Public Property Version As String
End Class
Public Class Policy
<JsonProperty("policy_type")>
Public Property PolicyType As String
<JsonProperty("policy_id")>
Public Property PolicyId As String
Public Property Applied As Boolean
<JsonProperty("settings_hash")>
Public Property SettingsHash As String
<JsonProperty("assigned_date")>
Public Property AssignedDate As DateTimeOffset
<JsonProperty("applied_date")>
Public Property AppliedDate As DateTimeOffset
<JsonProperty("rule_groups")>
Public Property RuleGroups As List(Of Object)
End Class
Dim restApiResponse2 = JsonConvert.DeserializeObject(Of RestApiResponseRoot2)(dr)
Dim resources As List(Of Resource) = restApiResponse2.Resources
' DeviceId of the first Resources object
Dim deviceId = resources(0).DeviceId
You can use some on-line resources to handle your JSON objects:
JSON Formatter & Validator
QuickType - JSON to .Net classes - C#, no VB.Net
JSON Utils - JSON to .Net classes - includes VB.Net. Somewhat less capable than QuickType.
Try trimming the resources value with " character in first and last of the output

Trying to parse JSON: Current JsonReader item is not an object

I already know to parse JSON in Java, but when I try to do it in VB.NET I get this error:
Newtonsoft.Json.JsonReaderException: 'Error reading JObject from JsonReader. Current JsonReader item is not an object: StartArray. Path '', line 1, position 1.'*
This is the code:
Dim requestUrl = "https://financialmodelingprep.com/api/v3/quote/TSLA?apikey={API_KEY}"
Dim jsonCode As String = New WebClient().DownloadString(requestUrl)
Dim json As JObject = JObject.Parse(jsonCode)
Dim price = json.SelectToken("price")
MsgBox(price)
End Sub
The message contained in the JSON is this:
[ {
"symbol" : "TSLA",
"name" : "Tesla, Inc.",
"price" : 431.38000000,
"changesPercentage" : 0.33000000,
"change" : 1.43000000,
"dayLow" : 427.76000000,
"dayHigh" : 452.50000000,
"yearHigh" : 502.49000000,
"yearLow" : 65.42000000,
"marketCap" : 408905547776.00000000,
"priceAvg50" : 423.72656000,
"priceAvg200" : 306.00583000,
"volume" : 28554811,
"avgVolume" : 63881259,
"exchange" : "NASDAQ",
"open" : 439.50000000,
"previousClose" : 429.95000000,
"eps" : 0.52300000,
"pe" : 824.81836000,
"earningsAnnouncement" : "2020-10-21T16:07:16.000+0000",
"sharesOutstanding" : 947901033,
"timestamp" : 1604951080
} ]
I would like to extract "price" and put it in a double.
Since you know what the incoming payload looks like, you should go ahead and create a class to represent the object:
Public Class Quote
Public Property symbol As String
Public Property name As String
Public Property price As Double
Public Property changesPercentage As Double
Public Property change As Double
Public Property dayLow As Double
Public Property dayHigh As Double
Public Property yearLow As Double
Public Property marketCap As Double
Public Property priceAvg50 As Double
Public Property priceAvg200 As Double
Public Property volume As Double
Public Property avgVolume As Double
Public Property exchange As String
Public Property open As Double
Public Property previousClose As Double
Public Property eps As Double
Public Property pe As Double
Public Property earningsAnnouncement As DateTimeOffset
Public Property sharesOutstanding As UInteger
Public Property timestamp As UInteger
End Class
From here you can use the DeserializeObject method to deserialize the array, get the first item in the collection, and then get the necessary properties:
Dim quotes = JsonConvert.DeserializeObject(Of List(Of Quote))(jsonCode)
Dim tesla = quotes?.SingleOrDefault()
If (tesla IsNot Nothing) Then
Console.WriteLine(tesla.price)
End If

How to deserialize JSON which can be an array or a single object

I'm fairly new to using JSON.net and having trouble with some json I'm getting which sometime comes in as an array and sometimes as single object. Here is an example of what I'm seeing with the json
One way it comes in ...
{
"Make": "Dodge",
"Model": "Charger",
"Lines": [
{
"line": "base",
"engine": "v6",
"color": "red"
},
{
"line": "R/T",
"engine": "v8",
"color": "black"
}
],
"Year": "2013"
}
Another way it could come in
{
"Make": "Dodge",
"Model": "Charger",
"Lines": {
"line": "base",
"engine": "v6",
"color": "red"
},
"Year": "2013"
}
Here is what I've been using for code which works on the first way and throws an exception in the second case. Been scouring the web for ways to implement this and am really stuck.
Public Class jsonCar
Public Property make As String
Public Property model As String
Public Property lines As List(Of jsonCarLines)
Public Property year As String
End Class
Public Class jsonCarLines
Public Property line As String
Public Property engine As String
Public Property color As String
End Class
Module Module1
Private Const json As String = "{""Make"":""Dodge"",""Model"":""Charger"",""Lines"": [{""line"":""base"",""engine"": ""v6"",""color"":""red""},{""line"":""R/T"",""engine"":""v8"",""color"":""black""}],""Year"":""2013""}"
'Private Const json As String = "{""Make"":""Dodge"",""Model"":""Charger"",""Lines"": {""line"":""R/T"",""engine"":""v8"",""color"":""black""},""Year"":""2013""}"
Sub Main()
Dim car As jsonCar = JsonConvert.DeserializeObject(Of jsonCar)(json)
Console.WriteLine("Make: " & car.make)
Console.WriteLine("Model: " & car.model)
Console.WriteLine("Year: " & car.year)
Console.WriteLine("Lines: ")
For Each ln As jsonCarLines In car.lines
Console.WriteLine(" Name: " & ln.line)
Console.WriteLine(" Engine: " & ln.engine)
Console.WriteLine(" Color: " & ln.color)
Console.WriteLine()
Next
Console.ReadLine()
End Sub
End Module
I'm guessing this will likely need a custom JsonConverter, but I'm a bit at a loss as to how to set that up.
Here is how to get the SingleOrArrayConverter solution in the linked duplicate question working for your use case.
First, here is the VB-translated converter code. Take this and save it to a class file somewhere in your project. You can then easily reuse it for any future cases like this.
Imports Newtonsoft.Json
Imports Newtonsoft.Json.Linq
Public Class SingleOrArrayConverter(Of T)
Inherits JsonConverter
Public Overrides Function CanConvert(objectType As Type) As Boolean
Return objectType = GetType(List(Of T))
End Function
Public Overrides Function ReadJson(reader As JsonReader, objectType As Type, existingValue As Object, serializer As JsonSerializer) As Object
Dim token As JToken = JToken.Load(reader)
If (token.Type = JTokenType.Array) Then
Return token.ToObject(Of List(Of T))()
End If
Return New List(Of T) From {token.ToObject(Of T)()}
End Function
Public Overrides ReadOnly Property CanWrite As Boolean
Get
Return False
End Get
End Property
Public Overrides Sub WriteJson(writer As JsonWriter, value As Object, serializer As JsonSerializer)
Throw New NotImplementedException
End Sub
End Class
Now that you have this converter, any time you have a property that can be either a list or a single item, all you have to do is declare it as a list in your class and then annotate that list with a JsonConverter attribute such that it uses the SingleOrArrayConverter class. In your case, that would look like this:
Public Class jsonCar
Public Property make As String
Public Property model As String
<JsonConverter(GetType(SingleOrArrayConverter(Of jsonCarLines)))>
Public Property lines As List(Of jsonCarLines)
Public Property year As String
End Class
Then, just deserialize as you normally would, and it works as expected.
Dim car As jsonCar = JsonConvert.DeserializeObject(Of jsonCar)(json)
Here is a complete demonstration: https://dotnetfiddle.net/msYNeQ
You could achieve this to modify your jsonCar class like below
Public Class jsonCar
Public Property make As String
Public Property model As String
Public Property linesCollection As List(Of jsonCarLines) // Change name
Public Property lines As String // Change the type to string
Public Property year As String
End Class
And the code should be like below:
Dim car As jsonCar = JsonConvert.DeserializeObject(Of jsonCar)(json)
If (car.lines.StartsWith("[")) Then
car.linesCollection = JsonConvert.DeserializeObject(List(Of jsonCarLines))(car.lines)
Else
car.linesCollection = new List(Of jsonCarLines)
car.linesCollection.Add(JsonConvert.DeserializeObject(Of jsonCarLines)(car.lines))
EndIf
Thanks to both crowcoder & Kundan. I combined the two approaches and came up with something that works with both json inputs. Here is the final code.
Public Class jsonCar
Public Property make As String
Public Property model As String
Public Property linesArray As List(Of jsonCarLines)
Public Property year As String
End Class
Public Class jsonCarLines
Public Property line As String
Public Property engine As String
Public Property color As String
End Class
Module Module1
'Private Const json As String = "{""Make"":""Dodge"",""Model"":""Charger"",""Lines"": [{""line"":""base"",""engine"": ""v6"",""color"":""red""},{""line"":""R/T"",""engine"":""v8"",""color"":""black""}],""Year"":""2013""}"
Private Const json As String = "{""Make"":""Dodge"",""Model"":""Charger"",""Lines"": {""line"":""R/T"",""engine"":""v8"",""color"":""black""},""Year"":""2013""}"
Sub Main()
Dim obj As JObject = JsonConvert.DeserializeObject(json)
Dim ln As JToken = obj("Lines")
Dim car As jsonCar = JsonConvert.DeserializeObject(Of jsonCar)(json)
If (ln.GetType() Is GetType(Newtonsoft.Json.Linq.JArray)) Then
car.linesArray = JsonConvert.DeserializeObject(Of List(Of jsonCarLines))(JsonConvert.SerializeObject(ln))
End If
If (ln.GetType() Is GetType(Newtonsoft.Json.Linq.JObject)) Then
car.linesArray = New List(Of jsonCarLines)
car.linesArray.Add(JsonConvert.DeserializeObject(Of jsonCarLines)(JsonConvert.SerializeObject(ln)))
End If
Console.WriteLine("Make: " & car.make)
Console.WriteLine("Model: " & car.model)
Console.WriteLine("Year: " & car.year)
Console.WriteLine("Lines: ")
For Each line As jsonCarLines In car.linesArray
Console.WriteLine(" Name: " & line.line)
Console.WriteLine(" Engine: " & line.engine)
Console.WriteLine(" Color: " & line.color)
Console.WriteLine()
Next
Console.ReadLine()
End Sub
End Module
Big thanks for the quick replies. This solved something I'd been spending a lot time off-and-on trying to figure out.
You can generically deserialize to Object and then inspect what you have. You can check for a JArray or JObject and act accordingly. You don't even need to deserialize into a specific type, you can work with the Dynamic objects but that may not be the best idea.
Module Module1
Sub Main()
Dim jsonWithArray As String = "{""Make"":""Dodge"",""Model"":""Charger"",""Lines"": [{""line"":""base"",""engine"": ""v6"",""color"":""red""},{""line"":""R/T"",""engine"":""v8"",""color"":""black""}],""Year"":""2013""}"
Dim jsonWithObject As String = "{""Make"":""Dodge"",""Model"":""Charger"",""Lines"": {""line"":""base"",""engine"": ""v6"",""color"":""red""},""Year"":""2013""}"
Dim witharray As Newtonsoft.Json.Linq.JObject = Newtonsoft.Json.JsonConvert.DeserializeObject(jsonWithArray)
Dim withstring As Newtonsoft.Json.Linq.JObject = Newtonsoft.Json.JsonConvert.DeserializeObject(jsonWithObject)
Dim jtokArray As Newtonsoft.Json.Linq.JToken = witharray("Lines")
Dim jtokStr As Newtonsoft.Json.Linq.JToken = withstring("Lines")
If (jtokArray.GetType() Is GetType(Newtonsoft.Json.Linq.JArray)) Then
Console.WriteLine("its an array")
End If
If (jtokStr.GetType() Is GetType(Newtonsoft.Json.Linq.JObject)) Then
Console.WriteLine("its an object")
End If
Console.ReadKey()
End Sub
End Module

Trouble parsing Json into .net Object

I've studied other questions like this and I'm not doing something right. My vb.net class is wrong or something. Should my class only try to represent from candidates on or what?
I need help with deserializing this json:
{
"spatialReference" : {
"wkid" : 2286
},
"candidates" : [
{
"address" : "100 MAIN ST",
"location" : {
"x" : 1144782.9490543604,
"y" : 81361.525678694248
},
"score" : 100,
"attributes" : {
}
},
{
"address" : "100 E MAIN ST",
"location" : {
"x" : 1120908.3257195801,
"y" : 169917.71846333146
},
"score" : 77,
"attributes" : {
}
}
]
}
I am using the following code to deserialize:
Public Shared Function Deserialise(Of T)(ByVal json As String) As T
Dim obj As T = Activator.CreateInstance(Of T)()
Using ms As MemoryStream = New MemoryStream(Encoding.Unicode.GetBytes(json))
Dim serializer As DataContractJsonSerializer = New DataContractJsonSerializer(obj.GetType())
obj = serializer.ReadObject(ms)
Return obj
End Using
End Function
And my vb.net class looks like this:
<DataContract()> _
Public Class SearchResults
Private mCandidates() As candidate
<DataContract()> _
Public Class SpatialReference
Private mwkId As String
<DataMember()> _
Public Property wkid() As String
Get
Return mwkId
End Get
Set(ByVal value As String)
mwkId = value
End Set
End Property
End Class
<DataMember()> _
Public Property Candidates() As candidate()
Get
Return mCandidates
End Get
Set(ByVal value As candidate())
mCandidates = value
End Set
End Property
End Class
<DataContract()> _
Public Class candidate
Private mAddress As String
Private mLocation As Location
Private mScore As String
Private mAttr As String
<DataMember()> _
Public Property address() As String
Get
Return mAddress
End Get
Set(ByVal value As String)
mAddress = value
End Set
End Property
<DataMember()> _
Public Property location() As Location
Get
Return mLocation
End Get
Set(ByVal value As Location)
mLocation = value
End Set
End Property
<DataMember()> _
Public Property score() As String
Get
Return mScore
End Get
Set(ByVal value As String)
mScore = value
End Set
End Property
<DataMember()> _
Public Property attributes() As String
Get
Return mAttr
End Get
Set(ByVal value As String)
mAttr = value
End Set
End Property
End Class
I dont know .net but i can tell you it related to JAVA. You can relate this with .Net
When we need to serialize or deserialize our class objects to json or from json we need Gson,
In Java we generally import tha package Gson package create its object for example:-
Suppose i have a class User, whose object you wanna serialize. Now to do this
take the whole object covert it to JSON with some key name with the help of Gson
jsonObject.put("KEYFORTHISjsonObject", gson.toJson(userClassObject));
Now you have serialized it to JSON,
While deserializing it
just create ur User object. Get Json Object from Json file
JSONObject jsonObject = new JSONObject(jsonFile.toString())
userObject2 = gson.fromJson(jsonObject.toString(), User.class);
so now userObject2 has all the values that you serialized earlier.
if you are not familiar with JAVA then Read about Gson for .net
or you can read this link as well http://james.newtonking.com/projects/json-net.aspx