Read REST API JSON reply - json

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

Related

How to iterate through all keys of json node

I'm trying to scrap the key values from this website API and it seems the json format it's not an array.
I'm working with console .Net core 6.0 using System.Text.Json.Nodes
The code I'm using is :
Dim streamData As Stream = Nothing
Using http As HttpClient = New HttpClient
Dim url As String = "https://api.hotbit.io/api/v1/market.status24h"
Dim t As Task(Of Stream) = http.GetStreamAsync(url)
streamData = t.Result
End Using
Dim jsonResponse As JsonNode = JsonNode.Parse(streamData)
Dim jsonData As JsonNode = jsonResponse("result")
Dim c As String = String.Empty
For Each jsonCurrency As JsonNode In jsonData.AsObject
c += jsonCurrency("last").ToString + " "
Next
but I get the error:
Cannot convert type 'KeyValuePair(Of String, JsonNode)' in JsonNode
What Am I doing wrong?
Thanks
Create a class to represent your JSON, like this:
Public Class MarketStatus
Public Property IsChange As Boolean
Public Property period As Integer
Public Property open As String
Public Property last As String
Public Property high As String
Public Property low As String
Public Property volume As String
Public Property deal As String
Public Property close As String
Public Property base_volume As String
Public Property quote_volume As String
End Class
Public Class Payload
Public Property _error As Object
Public Property result As Result
Public Property id As Integer
End Class
Public Class Result
<JsonPropertyName("0xBTCBTC")>
Public Property _0xBTCBTC As MarketStatus
<JsonPropertyName("0xBTCETH")>
Public Property _0xBTCETH As MarketStatus
<JsonPropertyName("0xCASHUSDT")>
Public Property _0xCASHUSDT As MarketStatus
<JsonPropertyName("1INCH1D3LUSDT")>
Public Property _1INCH1D3LUSDT As MarketStatus
' etc...
End Class
Now you can deserialize the entire payload by using JsonSerializer.Deserialize or JsonSerializer.DeserializeAsync:
Dim payloadObject = Await JsonSerializer.DeserializeAsync(Of Payload)(streamData)
Update
Per our conversation in the comments of this answer, you want to get the last value of each MarketStatus without having to type each one manually. What you can do is:
Use reflection to get every property of the Result class
Loop over the collection
Use PropertyInfo.GetValue to get the value of the deserialized object
Here is an example using the same variable names as above:
For Each propertyInformation In GetType(Result).GetProperties()
Dim status = DirectCast(propertyInformation.GetValue(payloadObject.result), MarketStatus)
Console.WriteLine("{0}.last = {1}", propertyInformation.Name, status.last)
Next
Fiddle: https://dotnetfiddle.net/USaAgc
I solved using
Dim result As JsonObject = jsonResponse("result").AsObject
For Each kvp In result.AsEnumerable
c &= kvp.Value("last").ToString & ", "
Next

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

How to deserialize nested JSON arrays with Json.Net?

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

How to deserialize a List(Of Object) from JSON?

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.

Getting Values of a JSON Object in vb.net

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.