VB.NET Json request - vb.net

Having some trouble trying to convert my json data to something usable
my json data
{
"4": {
"name": "Warehouse",
"tenantcode": "242",
"package_id": 1,
"package": "package10",
"ext_length": 4,
"country_id": 91,
"country_code": 61
},
"5": {
"name": "Partners",
"tenantcode": "240",
"package_id": 1,
"package": "package10",
"ext_length": 4,
"country_id": 91,
"country_code": 61
},
"8": {
"name": "Systems",
"tenantcode": "241",
"package_id": 20,
"package": "Systems",
"ext_length": 4,
"country_id": 91,
"country_code": 61
},
VB code
Imports System.Net
Imports Newtonsoft.Json
Imports Newtonsoft.Json.Linq
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim json2 As String = (New WebClient).DownloadString("https://myapi")
Dim json As String = json2
Dim ser As JObject = JObject.Parse(json)
Dim data As List(Of JToken) = ser.Children().ToList
For Each item As JProperty In data
item.CreateReader()
Select Case item.Name
Case "Name"
this is a far as i got.
i need to know whats the best was to try and use my json data.
build a new class?

Yes, you should build a new class. The data you provided can be deserialized as a Dictionary, so you'd just have to make a class for the details.
Public Class Details
Public Property Name As String
Public Property Tenantcode As String
Public Property Package_id As Integer
Public Property Package As String
Public Property Ext_length As Integer
Public Property Country_id As Integer
Public Property Country_code As Integer
End Class
Then simply deserialize your data into a Dictionary(String, Details)
Dim data = JsonConvert.DeserializeObject(Of Dictionary(Of String, Details))

Visual Studio has a cool feature called Paste JSON as Classes that can be found under Edit > Paste Special > Paste JSON as Classes. If you were to do this, then you would get something that looks like the following:
Public Class Rootobject
Public Property _4 As _4
Public Property _5 As _5
End Class
Public Class _4
Public Property name As String
Public Property tenantcode As String
Public Property package_id As Integer
Public Property package As String
Public Property ext_length As Integer
Public Property country_id As Integer
Public Property country_code As Integer
End Class
Public Class _5
Public Property name As String
Public Property tenantcode As String
Public Property package_id As Integer
Public Property package As String
Public Property ext_length As Integer
Public Property country_id As Integer
Public Property country_code As Integer
End Class
Since the Rootobject is basically acting like an associative array (in PHP) or dictionary (in .NET), then what I would do is get rid of Rootobject and _4, and rename _5 to be something a little more generic. Also, you can use decorators to make the property names conform to a more .NET style if you wanted:
Public Class Record
<JsonProperty("name")>
Public Property Name As String
<JsonProperty("tenantcode")>
Public Property TenantCode As String
<JsonProperty("package_id")>
Public Property PackageId As Integer
<JsonProperty("package")>
Public Property Package As String
<JsonProperty("ext_length")>
Public Property ExtLength As Integer
<JsonProperty("country_id")>
Public Property CountryId As Integer
<JsonProperty("country_code")>
Public Property CountryCode As Integer
End Class
Now what you'd do is create your webclient, download the string, and use DeserializeObject to convert the associative array to a dictionary:
Dim records As Dictionary(Of Integer, Record)
Using client As New WebClient()
Dim payload As String = client.DownloadString("https://myapi")
records = JsonConvert.DeserializeObject(Of Dictionary(Of Integer, Record))(payload)
End Using
Now you can get the object by it's key and access it's properties. E.g.:
If (records.ContainsKey(4)) Then
Console.WriteLine(records(4).Name)
End If

Related

How To Access Data In A Class Within A Class With VB.NET

I am relatively new to VB.NET Classes that define data structures. Also the terminology is a little unfamiliar.
I have defined the following Class structures:
Public Class CatalogInfoDef
Public CatalogName As String
Public CatalogYear As String
Public CatalogNumber As String
End Class
Public Class ParameterDef
Public Country As String
Public GeographicArea As String
Public Catalogs As List(Of CatalogInfoDef)
Public Class IssueDate
Public Month As String
Public Day As String
Public Year As String
End Class
Public Class Size
Public Width As String
Public Height As String
End Class
Public Printer As String
Public SearchKeywords As List(Of String)
Public Class OtherInfo
Public Condition As String
Public PrintMethod As String
End Class
End Class
In the Main Form I have the definition: Private ParameterInfo as New ParameterDef
I am able to insert data into the fields that are in the main Class, Country, etc.. However, I am having problems inserting data into fields such as: IssueDate (Month, Day, Year).
How do I access the data in these Class fields? Am I missing some parameter? Is there a better way to define ParameterDef?
What you're doing is defining classes within a class when it sounds like you want to define a property of a custom class. Something more along the lines of:
Public Class ParameterDef
Public Property Country As String
Public Property GeographicArea As String
Public Property Catalogs As List(Of CatalogInfoDef)
Public Property IssueDate As DateTime
Public Property Size As Size
Public Property Printer As String
Public Property SearchKeywords As List(Of String)
Public Property OtherInfo As OtherInfo
End Class
Public Class OtherInfo
Public Condition As String
Public PrintMethod As String
End Class
Then when you go to set the properties it would be:
Private ParameterInfo as New ParameterDef() With {
.Country = "...",
.GeographicArea = "..."
.Catalogs = New CatalogInfoDef() With {
.CatalogName = "...",
.CatalogYear = "...",
.CatalogNumber = "..."
},
.IssueDate = New DateTime(year, month, day) ' replace with actual values
.Size = New Size(width, height) ' replace with actual values
.Printer = "...",
.SearchKeywords = New List(Of String)(),
.OtherInfo = New OtherInfo() With {
.Condition = "...",
.PrintMethod = "..."
}
}
Also, notice how I removed your custom Date and Size class. This is because those classes already exist in the System and System.Drawing namespaces respectively.

Refer to a Class from within a With VB.net

I have called clientdetails which I wish to return as a whole to the JSONConvert Method to Serialize for JSON.
I have created a Class that has the Property Types I require (TextA,TextB) etc.
I can refer to both TransactionCount and TransactionType because they are part of ClientDetails, however when I try to refer to TextA of Transactions it states that TextA is not a member of ClientDetails - this I know which is why I explicitly state .Transactions.TextA.
If I declare Transactions separate under a new variable then I am able to refer to them however I need them to all be declared under ClientDetails to pass to the Serializer.
Can anyone point me out what I'm doing wrong here? Still learning.
Public Class JSON
Public Shared Function SerializeObject()
Dim clientdetails As New ClientDetails() With {.TransactionCount = "1", .TransactionType = "Q", .Transactions.TextA} 'Unable to Refer to any Property of Transactions.
'Dim Trans As New Transactions()
'Trans.TextA= "Test"
Dim output As String = JsonConvert.SerializeObject(clientdetails, Newtonsoft.Json.Formatting.Indented)
Return output
End Function
End Class
Public Class ClientDetails
Public Property Transactions As New Transactions()
Public Property [TransactionType] As String
Public Property [TransactionCount] As Integer
End Class
Public Class Transactions
Public Property [RecordID] As String
Public Property No As String
Public Property TextA As String
Public Property TextB As String
Public Property Initial As String
Public Property Flag As String
Public Property Sex As String
Public Property Area As String
Public Property Type As String
Public Property IDNO As String
End Class
You can use this syntax:
Dim clientdetails As New ClientDetails() With {.TransactionCount = "1", .TransactionType = "Q", .Transactions = New Transactions() With {.TextA = "Test"}}
Or a more readable code:
Dim trans As New Transactions
trans.TextA = "Test"
Dim clientDetails As New ClientDetails()
With clientDetails
.TransactionCount = "1"
.TransactionType = "Q"
.Transactions = trans
End With

Code to for AutoMapper complex mapping

AutoMapper with VB.NET
I have the following classes below. OrderA With List (Of OrderALineItem) and OrderBList With List (Of OrderB). I want to copy data from OrderA to OrderBList. Which copies ItemName, ItemQty, Price from List (Of OrderALineItem) to List (Of OrderB) and OrderID, CustomerName from OrderA itself. I have found almost all codes in C# and am not able to convert it to vb.net code.
Public Class OrderA
Public Property OrderID As String
Public Property CustomerName As String
Public Property OrderLineItem As List(Of OrderALineItem)
End Class
Public Class OrderALineItem
Public Property ItemName As String
Public Property ItemQty As Integer
Public Property Price As Decimal
End Class
Public Class OrderBList
Public Property OrderBLineItem As List(Of OrderB)
End Class
Public Class OrderB
Public Property OrderID As String
Public Property CustomerName As String
Public Property ItemName As String
Public Property ItemQty As Integer
Public Property Price As Decimal
End Class
My VB.NET code until now is:
Dim mapperConfiguration = New MapperConfiguration(Sub(config)
config.CreateMap(Of OrderALineItem, OrderBList)()
End Sub)
Dim mapper = mapperConfiguration.CreateMapper()
Dim objOrderB = mapper.Map(Of OrderBList)(objOrder.OrderLineItem)
The above code creates and object from copies the data from objOrder.OrderLineItem to OrderBList. That's it.
Can anybody help me out on this in VB.NET.
Note: Am totally new in AutoMapper
Version: AutoMapper 6.2.2.0
Done myself, I hope the code below will be helpful to somebody.
Dim mapperConfiguration = New MapperConfiguration(Sub(config)
config.AddProfile(New CustomProfile_1)
End Sub)
Dim objMapper = mapperConfiguration.CreateMapper()
Dim objOrderB As List(Of Dest_OrderB) = objMapper.Map(Of Src_OrderA, List(Of Dest_OrderB))(objOrderA)
Public Class CustomProfile_1
Inherits Profile
Sub New()
CreateMap(Of Src_OrderALineItem, Dest_OrderB)()
CreateMap(Of Src_OrderA, List(Of Dest_OrderB))() _
.ConstructProjectionUsing(
Function(Src1) Src1.List_Src_OrderALineItem.Select(Function(Src2) New Dest_OrderB _
With {.CustomerName = Src1.CustomerName,
.OrderID = Src1.OrderID,
.ItemName = Src2.ItemName,
.ItemQty = Src2.ItemQty,
.Price = Src2.Price}
).ToList())
End Sub
End Class

Simple JSON deserialisation for dummies

Trying to deserialise the following json returned from a web source:
{
"cards": [
{
"high": "8.27",
"volume": 5,
"percent_change": "0.00",
"name": "Wurmcoil engine",
"url": "http://blacklotusproject.com/cards/Scars+of+Mirrodin/Wurmcoil+Engine/",
"price": "6.81",
"set_code": "SOM",
"average": "5.67",
"change": "0.00",
"low": "1.12"}],
"currency": "USD"
}
I am using json.net with visual basic, new to both of them, especially the object oriented portions of vb. I would just like to extract the 'price' variable.
I have set up a class as such:
Public Class Card
Public high As String
Public volume As String
Public percent_change As String
Public name As String
Public url As String
Public price As String
Public set_code As String
Public average As String
Public change As String
Public low As String
End Class
The code I am currently using is:
Public Sub parse_json(url As String)
Dim blp_json As String = ""
Dim wClient As New WebClient
wClient.Proxy = System.Net.HttpWebRequest.DefaultWebProxy
blp_json = wClient.DownloadString(url)
MessageBox.Show(blp_json)
Dim card_1 = Newtonsoft.Json.JsonConvert.DeserializeObject(Of Card)(blp_json)
PriceTextBox.Text = card_1.price
TextBox1.AppendText(card_1.ToString)
TextBox1.AppendText(blp_json)
End Sub
Just trying many different things to get a hang of it, not really sure what I am doing. I presume my Card class is incorrect as 'price' appears to be nested in cards:[{...}]
I don't really know about deserialising json at all, and much less about how to do it /properly/ in vb.
I use the System.Web.Script.Serialization.JavaScriptSerializer for JSON deserialization. Your example is slightly complicated by the fact that cards contains an array of JSON objects. This is indicated by the "[" and "]". This example code will show you how to process it regardless of whether cards is an array or not. You may wish to ignore the Else if you are sure that there will always be an array in cards
Make sure that you have included a reference to System.Web.Extensions in your project and...
Imports System.Web.Script.Serialization
and then...
Dim MySerializer As JavaScriptSerializer = New JavaScriptSerializer()
Dim dictResult As Dictionary(Of String, Object) = MySerializer.Deserialize(Of Dictionary(Of String, Object))(blp_json)
Dim dictCard As Dictionary(Of String, Object)
If dictResult.ContainsKey("cards") Then
If TypeOf dictResult("cards") Is ArrayList Then
Dim arrResult As ArrayList = DirectCast(dictResult("cards"), ArrayList)
For Each arrCardRecord In arrResult
dictCard = DirectCast(arrCardRecord, Dictionary(Of String, Object))
If dictCard.ContainsKey("price") Then Console.WriteLine(dictCard("price"))
Next
Else
dictCard = DirectCast(dictResult("cards"), Dictionary(Of String, Object))
If dictCard.ContainsKey("price") Then Console.WriteLine(dictCard("price"))
End If
End If

Unable to cast custom listviewitem class in vb.net

This is a followup question to another question I asked earlier. I thought I had everything I needed, but I'm running into another issue. I'm trying to use a custom listviewitem class that attaches additional information to a lisview item. Here is the class:
Public Class albumListViewItem
Inherits ListViewItem
Public hash As String
Public id As Integer
Public provider As String
Public providerID As String
Public providerURL As String
Public providerArtistID As String
Public albumName As String
Public albumType As String
Public numTracks As Integer
Public imageURLs() As String
Public genres() As String
Public styles() As String
Public label As String
Public year As String
Public country As String
Public rating As String
Public editorsPick As Boolean
Public sampleStreamURL As String
Public providerReview As String
End Class
When I try to cast a listviewitem to my custom class like this:
Dim albumItem As albumListViewItem = CType(lsvHidden.items.item(0), albumListViewItem)
I get the following error, "Unable to cast object of type 'System.Windows.Forms.ListViewItem' to type 'AudioMatic.albumListViewItem'."
What am I missing here?
From your previous question and this one, I think a better fit for your problem would be to use a regular ListViewItem and store the accessory information in ListViewItem.Tag
You can do
Dim listViewItem As New ListViewItem("SomeText")
Dim albumInfo As New albumListViewItem()
albumInfo.albumName = "SomeAlbum"
...
listViewItem.Tag = albumInfo
listView1.Items.Add(listViewItem)
and then retrieve it like this
Dim selectedItem As ListViewItem = listView1.SelectedItems(0).Item
Dim alubmInfo As albumListViewItem = TryCast(selectedItem.Tag, alubmListViewItem)
Dim albumName as String = albumInfo.albumName
see if this solution will work for you.
If you step through the code and watch the variable "lsvHidden.items.item(0)" you should be able to first tell if it is in fact of type "albumListViewItem" or something else. Are you sure it was albumListViewItem that was added to the list in the first place?
Some alternatives to what you are doing;
1. You can implement an object and store it in the tag of the ListViewItem.
2. The following article seems to describe another approach of adding Columns to the listview to allow storing extra information on the listview itself; http://www.codeproject.com/KB/list/ListViewExtendedItem.aspx
I can appreciate your situation as I would have expected that to work. And I can see advantages and reasons for doing it that way as well. Not sure if the code project sample is adaptable to what you need, so you'll need to review the concept.
The working code:
Public Class albumListViewItem
Inherits ListViewItem
Public hash As String
Public id As Integer
Public provider As String
Public providerID As String
Public providerURL As String
Public providerArtistID As String
Public albumName As String
Public albumType As String
Public numTracks As Integer
Public imageURLs() As String
Public genres() As String
Public styles() As String
Public label As String
Public year As String
Public country As String
Public rating As String
Public editorsPick As Boolean
Public sampleStreamURL As String
Public providerReview As String
End Class
Storing information using listviewitem.tag:
Dim listViewItem As New ListViewItem("SomeText")
Dim albumItem As New albumListViewItem
albumItem.albumName = "Test Album"
albumItem.id = "testid"
albumItem.Text = albumItem.albumName
albumItem.year = "2011"
albumItem.numTracks = 10
'....
listViewItem.Tag = albumItem
'add viewable items to listview
albumItem.SubItems.Add(albumItem.year)
albumItem.SubItems.Add(albumItem.numTracks)
'....
ListView1.Items.Add(albumItem)
Reading the information that was previously stored:
Dim albumInfo As albumListViewItem = CType(ListView1.SelectedItems(0), albumListViewItem)
Dim id as string = alumInfo.id