I have the following json:
{
"Header": {
"MCC": "415",
"FO": "0",
"REGID": "5"
},
"Contacts": [
{
"NAME": "jocelyne",
"MO": "70123456"
},
{
"NAME": "eliane",
"MO": "03123456"
}
] }
I have 2 clients: one client is giving me this json in this order, the second is giving me the mo before name in the json, but I need to have the same order in the datatable all the time when I deserialize the json.
What I need to know which is the better way?
1-to deserialize the json in a list (it takes the tags in the alphabetic order) and then convert the list to a datatable
in this case that's what i'm doing:
Public Class Dataa
Public MCC As Integer
Public FO As Integer
Public RegId As Integer
Public Contacts As Contacts()
End Class
<Serializable()> _
Public Class Contacts
Public name As String
Public mo As String
End Class
Dim jss As New JavaScriptSerializer
Dim oFareResults As Generic.List(Of Dataa) = jss.Deserialize(Of List(Of Dataa))(json)
contactsDT = ConvertListToDataTable(oFareResults)
contactsDT.Columns.Add("taken_mo", GetType(String))
contactsDT.Columns.Add("reg_id", GetType(Integer))
Private Shared Function ConvertListToDataTable(oFareResults As List(Of Dataa)) As DataTable
' New table.
Dim dtTable As New DataTable()
dtTable.Columns.Add("name", GetType(String))
dtTable.Columns.Add("mo", GetType(String))
For i As Integer = 0 To oFareResults.Item(0).Contacts.Length - 1
dtTable.Rows.Add(oFareResults(0).Contacts(i).name, oFareResults(0).Contacts(i).mo)
Next
Return dtTable
End Function
2-to select 2 cases, every case for a different client and then deserialize the json in a datatable
in this case:
Public Class Data
Public Header As Header
Public Contacts As DataTable
End Class
<System.Runtime.Serialization.DataContract()>
Public Class Header
<System.Runtime.Serialization.DataMember(Name:="MCC")>
Public MCC As Integer
<System.Runtime.Serialization.DataMember(Name:="FO")>
Public FO As Integer
<System.Runtime.Serialization.DataMember(Name:="REGID")>
Public RegId As Integer
End Class
Dim data As New Data
data = JsonConvert.DeserializeObject(Of Data)(json)
mcc = data.Header.MCC
FO = data.Header.FO
regid = data.Header.RegId
contactsDT = data.Contacts
that's how i have to deserialize the json into a datatable and in this case i have to have 2 functions to deserialize one for every client ( to reserve the order that i need)
Well, what I need to know is not the general solution but I need to know which one has a better performance for the server considering that my json may be very long.
so i need the advantages and disadvantages of each case
Related
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
I want to deserialize the response of a HTTP-Request to Objects.
The Response looks like this:
[
"BeginOfEnumerable",
[
{
"StatusID": 12345,
"ItemID": 987654
}
],
"EndOfEnumerable"
]
I am using Newtonsoft.Json.
I tried to use Visual Studio's Edit > Paste special > Paste JSON as Classes to create the class model, but the result looks strange to me:
Public Class Rootobject
Public Property Property1() As Object
End Class
Also, this throws an Exception:
Dim myObject As Rootobject = JsonConvert.DeserializeObject(response.Content)
» Unexpected character encountered while parsing value: .Path ", line
0, position 0.
I want to get the StatusID and ItemID.
A JSON Validator I used says this JSON is valid.
The JSON structure is valid, per se, you may have some difficulty with the strings that don't follow the name:value pattern.
You could deserialize only the inner array of values, as a List(class), e.g.,
Imports System.Collections.Generic
Imports Newtonsoft.Json
Imports Newtonsoft.Json.Linq
Public Class EnumObject
Public Property StatusId As Long
Public Property ItemId As Long
End Class
'[...]
Dim jsonEnumsTokens = JArray.Parse(response.Content)
Dim enumsArray = jsonEnumsTokens.Children.Skip(1).First().ToObject(Of List(Of EnumObject))()
which returns the list of EnumObject that contain the values, if that's all you're interested in and you don't need to handle this JSON in any other way, or serialize it back in the same form.
If you want to get the JSON representation of the arrays only:
Dim justTheArraysJson = jsonEnumsTokens.Children.Skip(1).First().ToString()
In case you want to perform deserialization and serialization, maintaining the structure, you could use a custom JsonConverter that handles this case.
The EnumObjectsConverter creates an intermediate structure that contains both the single strings and the array of values, contained in the EnumObjectArray property.
This also allows to serialize back to the original structure, if needed.
Call it as:
Dim enumArray = EnumObjectsHandler.Deserialize(response.Content)
Dim serialized = EnumObjectsHandler.Serialize(enumArray)
The EnumObjectsHandler class that provides the static methods for the serialization:
Public Class EnumObjectsHandler
Private Shared settings As JsonSerializerSettings = New JsonSerializerSettings() With {
.Converters = {New EnumObjectsConverter()}
}
Public Shared Function Deserialize(json As String) As List(Of EnumObjectsRoot)
Return JsonConvert.DeserializeObject(Of List(Of EnumObjectsRoot))(json, settings)
End Function
Public Shared Function Serialize(data As List(Of EnumObjectsRoot)) As String
Return JsonConvert.SerializeObject(data, settings)
End Function
Public Class EnumObject
Public Property StatusId As Long
Public Property ItemId As Long
End Class
Public Structure EnumObjectsRoot
Public Property EnumObjectArray As List(Of EnumObject)
Public Property Operation As String
Public Shared Widening Operator CType(objectArray As List(Of EnumObject)) As EnumObjectsRoot
Return New EnumObjectsRoot With {.EnumObjectArray = objectArray}
End Operator
Public Shared Widening Operator CType(op As String) As EnumObjectsRoot
Return New EnumObjectsRoot With {.Operation = op}
End Operator
End Structure
Friend Class EnumObjectsConverter
Inherits JsonConverter
Public Overrides Function CanConvert(t As Type) As Boolean
Return t Is GetType(EnumObjectsRoot)
End Function
Public Overrides Function ReadJson(reader As JsonReader, t As Type, existingValue As Object, serializer As JsonSerializer) As Object
Select Case reader.TokenType
Case JsonToken.String
Dim stringValue = serializer.Deserialize(Of String)(reader)
Return New EnumObjectsRoot() With {
.Operation = stringValue
}
Case JsonToken.StartArray
Dim arrayValue = serializer.Deserialize(Of List(Of EnumObject))(reader)
Return New EnumObjectsRoot() With {
.EnumObjectArray = arrayValue
}
End Select
Throw New Exception("EnumObjectsRoot could not be deserialized")
End Function
Public Overrides Sub WriteJson(writer As JsonWriter, untypedValue As Object, serializer As JsonSerializer)
Dim value = CType(untypedValue, EnumObjectsRoot)
If value.Operation IsNot Nothing Then
serializer.Serialize(writer, value.Operation)
Return
End If
If value.EnumObjectArray IsNot Nothing Then
serializer.Serialize(writer, value.EnumObjectArray)
Return
End If
Throw New Exception("EnumObjectsRoot could not be serialized")
End Sub
End Class
End Class
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
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
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