json object to VB.Net array / Dictionary - vb.net

I have been tasked with adding a REST server to our company to work with an outside vendor. I have been able to complete most of it using VB.Net. However I am not sure how to handle the example below where there are 3 descriptors (OrderNumber,Desination,ItemNumbers) and ItemNumbers is an array. There may be any number of ItemNumbers in a single post. For the others I have made a class with properties, how can I do this with an array? I am using Newtonsoft.Json. Please post an example and Thank You!
Public Class Quality 'Example of how I have done the other json Posts
Private OrderNumberValue As String
Public Property OrderNumber() As String
Get
Return OrderNumberValue
End Get
Set(ByVal value As String)
OrderNumberValue = value
End Set
End Property
Private DestinationValue As String
Public Property Destination() As String
Get
Return DestinationValue
End Get
Set(ByVal value As String)
DestinationValue = value
End Set
End Property
END CLASS
This is the example json being posted:
{
"OrderNumber": "SO-1234567890",
"Destination": "Dock1 / Floor / whatever",
"ItemNumbers": [
{
"ItemNumber": "400100",
"CasesRequired": "140"
},
{
"ItemNumber": "400200",
"CasesRequired": "140"
}
]
}

you can use Newtonsoft.Json
Imports Newtonsoft.Json
Dim order As Order = Newtonsoft.Json.JsonConvert.DeserializeObject(Of Order)(json)
and you need two classes
Public Class ItemNumber
Public Property ItemNumber As String
Public Property CasesRequired As String
End Class
Public Class Order
Public Property OrderNumber As String
Public Property Destination As String
Public Property ItemNumbers As ItemNumber()
End Class

Related

What is the codefirst syntax to add a simple list of an elementary type to a database table?

Hopefully I simplified everything well to focus on my question. I am defining a class to create a database using code first EF. When I do the following:
Public Class question
Public Property QuestionID As Integer
Public Property Answers As String
End Class
I get this in the migration file:
CreateTable(
"dbo.questions",
Function(c) New With
{
.QuestionID = c.Int(nullable:=False, identity:=True),
.Answers = c.String()
}) _
.PrimaryKey(Function(t) t.QuestionID)
So far, good. Now, when I try to change the second property to be a list of string as follows:
Public Class question
Public Property QuestionID As Integer
Public Property Answers As New List(Of String)
End Class
I get this in the migration file:
CreateTable(
"dbo.questions",
Function(c) New With
{
.QuestionID = c.Int(nullable:=False, identity:=True)
}) _
.PrimaryKey(Function(t) t.QuestionID)
The way I've written it does not generate a list of strings. Hopefully someone can illuminate the basic concept I'm missing here.
Don't create a text field with the answers, no!
You need to create a new table, the Answers table, then add a ForeignKey to your question table like this:
Public Class question
Public Property QuestionID As Integer
'Public Property Answers As String
Public Overridable Property Answers() as ICollection (Of Answer)
End Class
Public Class Answer
Public Property ID As Integer
Public Property questionID as Integer
Public Property Answers As String
<ForeignKey("questionID")>
Public Overridable Property Question as question
End Class
Then you just do this (C#):
IEnumerable<answer> answers=question1.Answers.ToList();

YamlDotNet - Serialization of Guid properties generates empty brackets

I am using YamlDotNet library to serialize some objects in Yaml. I've met some problems with the serialization of Guid properties.
Serialization of Guid properties generates empty brackets ( ex: {} )
See code below
Dim l As New List(Of Person)
l.Add(New Person() With {.Firstname = "MyFirstName", .Lastname = "MyLastName", .Id = Guid.NewGuid()})
Using sw As New StreamWriter("output.yaml", False)
Dim serializer = New Serializer()
serializer.Serialize(sw, l)
End Using
this code will output :
- Id: {}
Firstname: MyFirstName
Lastname: MyLastName
With the class:
Public Class Person
Public Property Id As Guid
Public Property Frstname As String
Public Property Lastname As String
End Class
Am I missing something or is this an issue of the library ?
You can define a custom converter to use when you need to customize the serialization of a type. The converter needs to implement IYamlTypeConverter, and be registered on the Serializer or Deserializer. Here is an example of such a converter:
Public Class GuidConverter
Implements IYamlTypeConverter
Public Function Accepts(type As Type) As Boolean Implements IYamlTypeConverter.Accepts
Return type = GetType(Guid)
End Function
Public Function ReadYaml(parser As IParser, type As Type) As Object Implements IYamlTypeConverter.ReadYaml
Dim reader = New EventReader(parser)
Dim scalar = reader.Expect(Of Scalar)()
Return Guid.Parse(scalar.Value)
End Function
Public Sub WriteYaml(emitter As IEmitter, value As Object, type As Type) Implements IYamlTypeConverter.WriteYaml
emitter.Emit(New Scalar(value.ToString()))
End Sub
End Class
The usage is quite simple:
Dim serializer = New Serializer()
serializer.RegisterTypeConverter(New GuidConverter())
serializer.Serialize(Console.Out, New With {.id = Guid.NewGuid()})
You can see a fully working example here.

vb.net json.net deserialization issue

I have an issue that is driving me nuts. I have a project to deserialize and process a json response:
[{"summary":[{"cardDate":"2013-08-06","cardId":46121,"contenderList":[1,2,3,4,5,7,8,10],"dateTime":"2013-08-06 10:36","marketList":["TOTE_WIN_PLACE","FORECAST","FORECAST_PLACE"],"raceId":465453,"raceNumber":2,"tote":"Australia","venue":"AU - Dog, Bendigo"}]
I have built classes to handle the response:
Public Class clsAXMeetList
Public Property summary() As clsAXRaceList()
End Class
Public Class clsAXRaceList
Public Property cardDate As String
Public Property cardID As Integer
Public Property [contenderList]() As clsAXContenderList()
Public Property dateTime As String
Public Property [marketList]() As clsAXMarketList()
Public Property raceID As String
Public Property raceNumber As Integer
Public Property tote As String
Public Property venue As String
End Class
Public Class clsAXContenderList
Public Property runners() As Integer
End Class
Public Class clsAXMarketList
Public Property [a] As String
Public Property [b] As String
Public Property [c] As String
End Class
but when the deserializer hits the first value in the contender list (1) it throws this error:
Error converting value 1 to type 'AsiaExchange.clsAXContenderList'. Path '[0].summary[0].contenderList[0]', line 1, position 71.
I have looked around and I cant find much help
The contenderList is an array of numbers, not objects. There is no conversion from numbers to arbitrary objects. You need to either change your contenderList property to an array of integers (Integer()) or provide a converter to your object. You will have to do the same for the marketList as well.

Sort Datagridview columns when datasource binded to List(Of T)

I have a datagridview with its datasource binded to a List(Of T). Now i would like to sort on any of the columns.
My code:
'Database access : items = List(BlogPost)
dgBlogPosts.DataSource = items
'My BlogPost Class
Public Class BlogPost
Public Property ID As Integer
Public Property Title As String
Public Property Content As String
Public Property CreationDate As DateTime
Public Property Rating As Decimal = 5.0
End Class
Take a look at this example which recommends using a BindingList instead and then a bit of code to enable sorting. There is also this on codeproject.

How can I access a class variable via an array in VB.NET?

If I have the following class and declaration:
Public Class objLocation
Public SysLocationId As String
Public NameFull As String
Public LatRaw As String
Public LongRaw As String
Public Active As Integer
End Class
dim lLocation as new objLocation
I can access each variable thus lLocation.SysLocationId, etc. Is there an alternate way, so I can access each variable by index, so something like lLocation(0), lLocation(1), etc., which gives me the flexibility to compare to classes of the same type via a for next loop, or against other sources, like a datatable.
If your goal is comparison, usually what you'll do is implement the IComparable interface or overload the >, < operators (if an ordering is needed) or just the = operator (if equivalence is needed).
You just write one function in one location and invoke that function whenever you need to do your comparison. The same goes for comparing to objects stored in a database. Where you put these functions depends on your application architecture, but for the object-object comparison you can have it as part of the objLocation class itself.
There is no built-in langauge support for this. However you can simulate this by creating a default indexer property on the class
Public Class objLocation
...
Default Public ReadOnly Property Indexer(ByVal index As Integer)
Get
Select Case index
Case 0
Return SysLocationId
Case 1
Return NameFull
Case 2
Return LatRaw
Case 3
Return LongRaw
Case 4
Return Active
Case Else
Throw New ArgumentException
End Select
End Get
End Property
Then you can use it as follows
Dim x As objLocation = GetObjLocation
Dim latRaw = x(2)
No, you can not do this outright.
You have to use reflection to get the properties, but you have to be aware that there is no guarantee on the order of the properties returned (which is important if you want to index them numerically).
Because of that, you will have to keep the sort order consistent when working with the properties (and indexes).
Are you looking for a List:
Dim LocationList As List<objLocation>;
For Each loc As objLocation In LocationList
loc.whatever
Next
or to use the index:
For i = 0 To LocationList.Length - 1
LocationList(i).whatever
Next
sorry, if the VB syntax isn't right...I've been doing C# lately and no VB
You can do that as follows. It is C# and something is a bit different with using indexers in VB, but you should absolutly be able to get it working in VB.
public class ObjLocation
{
private String[] Properties = new String[5];
public const Int32 IndexSysLocationId = 0;
public const Int32 IndexNameFull = 1;
public const Int32 IndexLatRaw = 2;
public const Int32 IndexLongRaw = 3;
public const Int32 IndexActive = 4;
// Repeat this for all properties
public String SysLocationId
{
get { return this.Properties[ObjLocation.IndexSysLocationId]; }
set { this.Properties[ObjLocation.IndexSysLocationId] = value; }
}
public String this[Int32 index]
{
get { return this.Properties[index]; }
set { this.Properties[index] = value; }
}
}
Now you have the object with the properties as before, but stored in an array and you can also access them through an indexer.
This method I implemented in a public structure to return an array of string variables stored in a structure:
Public Shared Function returnArrayValues() As ArrayList
Dim arrayOutput As New ArrayList()
Dim objInstance As New LibertyPIMVaultDefaultCategories()
Dim t As Type = objInstance.GetType()
Dim arrayfinfo() As System.Reflection.FieldInfo = t.GetFields()
For Each finfo As System.Reflection.FieldInfo In arrayfinfo
Dim str As String = finfo.GetValue(objInstance)
arrayOutput.Add(str)
Next
Return arrayOutput
End Function
Put it inside the structure or a class. Maybe this sample code helps.