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
Related
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 have a List(Of Object) that I am using in a property of type IEnumerable(Of Object). I can serialize it fine but cannot work out then how to deserialize it from JSON back to a List(Of Object). Any help would be really great please.
My ViewModel:
Public Class ViewModel
Inherits ViewModelBase
Public Class MapSettings
<Display(Name:="Map Name", Description:="Enter a optional name for the map.", GroupName:="Map Settings")>
Public Property MapName As String
<Display(Name:="Map Description", Description:="Enter a optional description for the map.", GroupName:="Map Settings")>
Public Property MapDescription As String
<Display(Name:="Map Comments", Description:="Enter optional comments for the map.", GroupName:="Map Settings")>
Public Property MapComments As String
<Display(Name:="Map Version", Description:="Enter a optional version for the map.", GroupName:="Map Settings")>
Public Property MapVersion As String
End Class
Public Class GeneralSettings
<Display(Name:="Route Colour", Description:="Sets the colour of the routes design line on the map.", GroupName:="General Settings")>
Public Property Foreground As Color
End Class
Private _myItems() As IEnumerable(Of Object)
Public Property MyItems() As IEnumerable(Of Object)
Get
If _myItems Is Nothing Then
Return New List(Of Object)() From {
New MapSettings,
New GeneralSettings With {.Foreground = Colors.Blue}
}
Else
Return _myItems
End If
End Get
Set(value As IEnumerable(Of Object))
_myItems = value
OnPropertyChanged()
End Set
End Property
End Class
My serialize code that I cannot complete:
Dim MyItems_New = JsonConvert.DeserializeObject(Of MyItems???)(MyJsonString)
JSON:
{
"MyItems": [
{
"MapName": null,
"MapDescription": null,
"MapComments": null,
"MapVersion": null
},
{
"Foreground": "#FF0000FF"
}
]
}
I just found that Newtonsoft has built-in support for type handling, which can be enabled by setting the JsonSerializerSettings.TypeNameHandling property and passing it to the serialization methods. As long as you control the input, this should let you both serialize and deserialize your list without a problem.
Serialize:
Dim myItems = JsonConvert.SerializeObject(myVM.MyItems, Formatting.None, New JsonSerializerSettings() With { .TypeNameHandling = TypeNameHandling.Auto })
Deserialize:
Dim myItems_New = JsonConvert.DeserializeObject(Of List(Of Object))(MyJsonString, New JsonSerializerSettings() With { .TypeNameHandling = TypeNameHandling.Auto })
In your question, MyJsonString appears to be a serialized version of your ViewModel class rather than just the list itself. If this is the case, change DeserializeObject(Of List(Of Object)) to DeserializeObject(Of ViewModel).
Resulting JSON:
[
{
"$type": "MapSettings, YourProjectNamespace",
"MapName": "New York",
"MapDescription": "Map over New York",
"MapComments": null,
"MapVersion": "v1"
},
{
"$type": "GeneralSettings, YourProjectNamespace",
"Foreground": "#FF0000"
}
]
Try it online (C#):
https://dotnetfiddle.net/0jCIGL
However, if these two classes are all you are planning to use this list for, then you'd be better off using something along the lines of Jimi's proposed solution, as then you're always working with strongly-typed objects.
I have a rest API which returns me a json response which is an array of docs which in turn has multiple arrays it self. Below is a sample of a doc i like to deserialize
{
"DocId": "contact::6f128681-218d-409d-b71d-31031852057d",
"Name": "Joe F Miller",
"buckets": [
{
"DocId": "leadbucket::5652A756-5B58-45A5-9566-9C85E8783440",
"text": "Dead Leads"
},
{
"DocId": "leadbucket::8A234FC1-6389-485D-8BDE-7FCB1E7639E0",
"text": "No Follow-Up Needed"
},
{
"DocId": "leadbucket::C97632BE-5A24-4AE7-8D18-4DFE174F0D0F",
"text": "Long-Term Buyers"
},
{
"DocId": "leadbucket::D6802064-8AC5-4E5A-855E-B59C32859C81",
"text": "New Lead"
}
],
"emails": [
{
"other": "demo#test.com"
},
{
"work": "work#demo.com"
},
{
"work": "work2#demo.com"
}
],
"followup": {
"date": "05/01/2019",
"type": "phone"
},
"lastactivity": "04/05/2019",
"phones": [
{
"home": "(213) 444-2222"
},
{
"work": "(949) 555-1212"
}
],
"tags": [
{
"DocId": "tag::FC276FBD-DC3A-4E18-8244-E89EF24E022E",
"text": "Buyer"
},
{
"DocId": "tag::EA5DE0FB-34B0-4F7C-B631-177D6BD2F65E",
"text": "Investor"
}
]
}
After i get the response from my API i use the below code to try to convert the data.
ContactList = JsonConvert.DeserializeObject(Of List(Of Contact.ContactList))(read.Item("Data").ToString)
So i hope someone can point me in the right direction on how to create a class to store this type of doc and how to Deserialize it. Do i have to do this in my class or do i have to call a Deserialize for each array in the Json ?
Another issue i have is the emails and phones section, as the key value is not unique and i dont always know what will get returned. how would i build a class to store this as the key field can change.
An example, using an IEnumerable(Of Dictionary(Of String, String)) to deserialize JSON Objects that have an undefined number of elements, with an undefined combination of (Key, Value) pairs per object.
The Key part may also repeat, as shown in the exmple:
"emails": [
{"other": "demo#test.com"},
{"work": "work#demo.com"},
{"work": "work2#demo.com"}
The other, work keys may be different each time and may repeat.
Deserializing/Serializing this property with a IEnumerable(Of Dictionary(Of String, String)), allows to
The sample class object, Contacts, contains the methods (simplified, here) that perform the deserialization of the JSON Object and the seriaization of the Object Root, reproducing the original JSON Object.
These methods are static (Shared), you just need to call the method, no need to create an instance of the Contacts class.
For example, deserialize a JSON Object (a string received from a service):
Dim myContacts As Contacts.RootObject = Contacts.DeserializeJSON(JSONObject)
Serialize the class object back to the original string:
Dim myJsonContacts = Contacts.SerializeJSON(myContacts)
Compare the JSON just serialized to the original and to see whether they match.
List all the Emails and Phone Numbers in the deserialized class object:
(just an example: converting to List is not necessary)
myContacts.Emails.ToList().ForEach(
Sub(em) Console.WriteLine($"from: {em.Keys(0)}, Email: {em.Values(0)}"))
myContacts.Phones.ToList().ForEach(
Sub(ph) Console.WriteLine($"place: {ph.Keys(0)}, Phone Number: {ph.Values(0)}"))
Access a single Email (or Phone Number):
(any other method to extract the (Key, Value) pair from a Dictionary can of course be used)
Dim eMailFrom = myContacts.Emails(0).Keys(0)
Dim eMailValue = myContacts.Emails(0).Values(0)
Get all the Emails from a specific location (work, here):
Dim emailFromWork = myContacts.Emails.Where(Function(em) em.Keys.Contains("work"))
The Contacts class:
Some properties are decorated with a <JsonProperty()>. The property name is changed because the original JSON uses names that are reserved keywords in the language.
For example:
<JsonProperty("text")>
Public Property BucketText As String
Imports Newtonsoft.Json
Public Class Contacts
Public Shared Function DeserializeJSON(JsonObject As String) As RootObject
Return JsonConvert.DeserializeObject(Of RootObject)(JsonObject)
End Function
Public Shared Function SerializeJSON(classObject As RootObject) As String
Return JsonConvert.SerializeObject(classObject)
End Function
Partial Public Class RootObject
Public Property DocId As String
Public Property Name As String
Public Property Buckets As List(Of Bucket)
Public Property Emails As Dictionary(Of String, String)()
Public Property Followup As Followup
Public Property Lastactivity As String
Public Property Phones As IEnumerable(Of Dictionary(Of String, String))
Public Property Tags As List(Of Tag)
End Class
Partial Public Class Bucket
Public Property DocId As String
<JsonProperty("text")>
Public Property BucketText As String
End Class
Partial Public Class Tag
Public Property DocId As String
<JsonProperty("text")>
Public Property TagText As String
End Class
Partial Public Class Followup
<JsonProperty("date")>
Public Property FollowupDate As String
<JsonProperty("type")>
Public Property FollowupType As String
End Class
End Class
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
EDITED:
I got stuck while getting value of a JSON object in vb.net. My JSON request posts data like given below:
function submitEmail() {
var ClientsPersonalInfo = {
FullName: $("#FullName").val(),
PhoneNumber: $("#PhoneNumber").val(),
EmailAddress: $("#EmailAddress").val(),
DOB: $("#DOB").val(),
Occupation: $("#Occupation").val(),
NINumber: $("#NINumber").val(),
FullAddress: $("#FullAddress").val()
}
var ClientsData = {};
ClientsData.ClientsPersonalInfo = ClientsPersonalInfo;
var d = '{"ClientsData":' + JSON.stringify(ClientsData) + '}'
$.ajax({
type: "POST",
url: "add-new-client.aspx/SubmitEmail",
data: d,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (response) {
alert(response)
},
failure: function (msg) {
alert(msg);
}
});
}
JSON Object Looks Like
{
"ClientsPersonalInfo": {
"FullName": "",
"PhoneNumber": "",
"EmailAddress": "",
"DOB": "",
"Occupation": "",
"NINumber": "",
"FullAddress": ""
}
}
The above request returns an object in vb.net
VB Code:
<WebMethod()> _
Public Shared Function SubmitEmail(ByVal ClientsPersonalInfo As Object) As String
// What to do next to get object "ClientsPersonalInfo"
// I want to access properties of the object like
//Dim name As String = ClientsPersonalInfo.FullName
Return "Successfully Converted."
End Function
No I want to get values of this object and needs to append in a table. Please guide me how to get values of the above object?
First make sure your Json is in valid format using jsonlint
Then generate class base on it using jsonutils
Public Class ClientsPersonalInfo
Public Property FullName As String
Public Property PhoneNumber As String
Public Property EmailAddress As String
Public Property DOB As String
Public Property Occupation As String
Public Property NINumber As String
Public Property FullAddress As String
End Class
Public Class ClientsVehicleInfo
Public Property DrivingLicense As String
Public Property VehicleMakeModel As String
Public Property VehicleColour As String
Public Property PolicyNumber As String
Public Property TypeOfCover As String
Public Property VehicleStoredIn As String
End Class
Public Class ClientsData
Public Property ClientsPersonalInfo As ClientsPersonalInfo
Public Property ClientsVehicleInfo As ClientsVehicleInfo
End Class
Public Class ClientData
Public Property ClientsData As ClientsData
End Class
Use Newtonsoft JSON to deserialize your Json into object(s) then you may simply access its properties value. (remember to add Json.net to your project using Manage NuGet Packages)
Imports Newtonsoft.Json
Dim obj = JsonConvert.DeserializeObject(Of Dictionary(Of String, ClientsData))(yourJsonString)
At least one problem is not using Option Strict On. The code at fault:
Shared Function SubmitEmail(ByVal ClientData As Object) As String
Dim obj = JsonConvert.DeserializeObject(Of NewClientData)(ClientData)
If you turn on Option Strict that will not compile because JsonConvert.DeserializeObject takes a string argument. I am not sure why the exception (image now removed) seems to come from VB rather than Newtonsoft, but that isnt helping.
Your deserialized object will also just disappear when it goes out of scope when the method ends.
Applicable to Edit #9
The error mentioning a Dictionary seems misleading and probably something internal relating to how the properties are collected (many times json can be deserialized to a Dictionary(Of String, String). Given the json posted (with data):
{
"ClientsData": {
"ClientsPersonalInfo": {
"FullName": "Ziggy Le Strange",
"PhoneNumber": "505050",
"EmailAddress": "ziggy#foobar.com",
"DOB": "",
"Occupation": "Freelancer",
"NINumber": "7",
"FullAddress": "123 Easy street"
}
}
}
There are actually 3 classes: ClientsPersonalInfo with the data, ClientsData which is a class containing that one and in previous edits also included a ClientsVehicleInfo class.
But there is yet another class represented by the enclosing {...}. The robots who can create the classes for you name it Example or RootObject. In this case, I would call it ClientContainer.
This works:
' the outermost {}
Public Class ClientContainer
Public Property ClientsData As ClientsData
End Class
Public Class ClientsPersonalInfo
Public Property FullName As String
Public Property PhoneNumber As String
Public Property EmailAddress As String
Public Property DOB As String
Public Property Occupation As String
Public Property NINumber As String
Public Property FullAddress As String
End Class
Public Class ClientsData
Public Property ClientsPersonalInfo As ClientsPersonalInfo
Public Property ClientsVehicleInfo As ClientsVehicleInfo
End Class
Public Class ClientsVehicleInfo
' whatever it is supposed to hold
End Class
To deserialize the data (you may have to adapt it for web use, Shared seems incorrect to me):
' pass in the json AS STRING
' returns JUST the ClientsPersonalInfo
Public Function GetClientData(jsonData As String) As ClientsPersonalInfo
' you must use the container class
Dim client = JsonConvert.DeserializeObject(Of ClientContainer)(jsonData )
' TEST:
Console.WriteLine(client.ClientsData.ClientsPersonalInfo.FullName)
Return client.ClientsData.ClientsPersonalInfo
End Function
ClientsData seems to be an unneeded layer. The container could hold both of the other objects directly. If this is meant to hold info for more than one client, you would have keys in place of "ClientsData": in the json (e.g. "ziggy":{}, "zacky":{}, "zoey":{}.
Output:
Ziggy Le Strange
Since, as per comment, that vehicle info is part of the deal, you can change it to return ClientsData which holds both the Personal and Vehicle info:
Public Function GetClientData(jsonData As String) As ClientsData
' you must use the container class
Dim client = JsonConvert.DeserializeObject(Of ClientContainer)(jsonData )
Return client.ClientsData
Turn on Option Strict
Dont box parameters or returns As Object, they loose some of their meaning.
Keep in mind that the outermost braces in json represent a container object
Also, storing a Date as string looks bad too.