How to compare 2 JSON structures using VB.NET? - vb.net

I am new to JSON.NET. I am trying to compare 2 JSON structures using VB.NET like
{
"attrs":[
{
"name":"_DB_ATTR_OSD_PARENT_",
"column":"OsDeployerParent",
"type":"Integer",
"enumName":null
},
{
"name":"_DB_ATTR_SMALLICON_",
"column":"CurrentSmallIcon",
"type":"Enum"
}
]
}
Please can someone help me.
Thanks.

classes to be used
public class testObjects
{
public List<testObject> attrs;
}
public class testObject
{
public string name;
public string column;
public string type;
public string enumName;
}
Comparison preparing for class
class ObjectComparer : EqualityComparer<testObject>
{
public override bool Equals(testObject c1, testObject c2)
{
if (c1.name == c2.name &&
c1.column == c2.column &&
c1.enumName == c2.enumName &&
c1.type == c2.type)
{
return true;
}
else
{
return false;
}
}
public override int GetHashCode(testObject c)
{
int hash = 23;
if (c.name != null) hash = hash * 37 + c.name.GetHashCode();
if (c.column != null) hash = hash * 37 + c.column.GetHashCode();
if (c.enumName != null) hash = hash * 37 + c.enumName.GetHashCode();
if (c.type != null) hash = hash * 37 + c.type.GetHashCode();
return hash;
}
}
operations starts right here
string jsonObjects = #"{ 'attrs':[ { 'name':'_DB_ATTR_OSD_PARENT_', 'column':'OsDeployerParent', 'type':'Integer', 'enumName':null }, { 'name':'_DB_ATTR_SMALLICON_', 'column':'CurrentSmallIcon', 'type':'Enum' } ] }";
System.Web.Script.Serialization.JavaScriptSerializer js = new System.Web.Script.Serialization.JavaScriptSerializer();
var objects = js.Deserialize(jsonObjects, typeof(testObjects));
ObjectComparer cmp = new ObjectComparer();
testObjects deserializedObject = ((testObjects)objects);
// this allows you to remove double entries
var distinctObjects = deserializedObject.attrs.Distinct(cmp).ToList();
Console.WriteLine(string.Format("duplicate objects count : {0}", (deserializedObject.attrs.Count - distinctObjects.Count).ToString()));
//If you want to compare if the following code can be used individually
testObject obj1 = ((testObjects)objects).attrs.First();
testObject obj2 = ((testObjects)objects).attrs.Skip(1).First();
bool isObjectEquals = cmp.Equals(obj1, obj2);
Console.WriteLine(string.Format("Objects are {0}", isObjectEquals ? "Equals" : "Not Equals"));

this is vb code
classes to be used
Public Class testObjects
Public attrs As List(Of testObject)
End Class
Public Class testObject
Public name As String
Public column As String
Public type As String
Public enumName As String
End Class
Comparison preparing for class
Class ObjectComparer
Inherits EqualityComparer(Of testObject)
Public Overrides Function Equals(c1 As testObject, c2 As testObject) As Boolean
If c1.name = c2.name AndAlso c1.column = c2.column AndAlso c1.enumName = c2.enumName AndAlso c1.type = c2.type Then
Return True
Else
Return False
End If
End Function
Public Overrides Function GetHashCode(c As testObject) As Integer
Dim hash As Integer = 23
If c.name IsNot Nothing Then
hash = hash * 37 + c.name.GetHashCode()
End If
If c.column IsNot Nothing Then
hash = hash * 37 + c.column.GetHashCode()
End If
If c.enumName IsNot Nothing Then
hash = hash * 37 + c.enumName.GetHashCode()
End If
If c.type IsNot Nothing Then
hash = hash * 37 + c.type.GetHashCode()
End If
Return hash
End Function
End Class
operations starts right here
Dim jsonObjects As String = "{ 'attrs':[ { 'name':'_DB_ATTR_OSD_PARENT_', 'column':'OsDeployerParent', 'type':'Integer', 'enumName':null }, { 'name':'_DB_ATTR_SMALLICON_', 'column':'CurrentSmallIcon', 'type':'Enum' } ] }"
Dim js As New System.Web.Script.Serialization.JavaScriptSerializer()
Dim objects = js.Deserialize(jsonObjects, GetType(testObjects))
Dim cmp As New ObjectComparer()
Dim deserializedObject As testObjects = DirectCast(objects, testObjects)
' this allows you to remove double entries
Dim distinctObjects = deserializedObject.attrs.Distinct(cmp).ToList()
Console.WriteLine(String.Format("duplicate objects count : {0}", (deserializedObject.attrs.Count - distinctObjects.Count).ToString()))
'If you want to compare if the following code can be used individually
Dim obj1 As testObject = DirectCast(objects, testObjects).attrs.First()
Dim obj2 As testObject = DirectCast(objects, testObjects).attrs.Skip(1).First()
Dim isObjectEquals As Boolean = cmp.Equals(obj1, obj2)
Console.WriteLine(String.Format("Objects are {0}", If(isObjectEquals, "Equals", "Not Equals")))

New Codes
string jsonObjects = #"{ 'attrs':[ { 'name':'_DB_ATTR_OSD_PARENT_', 'column':'OsDeployerParent', 'type':'Integer', 'enumName':null }, { 'name':'_DB_ATTR_SMALLICON_', 'column':'CurrentSmallIcon', 'type':'Enum' } ] }";
string jsonObjects2 = #"{ 'attrs':[ { 'name':'_DB_ATTR_OSD_PARENT_', 'column':'OsDeployerParent1', 'type':'Integer', 'enumName':null }, { 'name':'_DB_ATTR_SMALLICON_', 'column':'CurrentSmallIcon', 'type':'Enum' } ] }";
System.Web.Script.Serialization.JavaScriptSerializer js = new System.Web.Script.Serialization.JavaScriptSerializer();
var objects = js.Deserialize(jsonObjects, typeof(testObjects));
var objects2 = js.Deserialize(jsonObjects2, typeof(testObjects));
ObjectComparer2 cmp = new ObjectComparer2();
testObjects deserializedObject = ((testObjects)objects);
testObjects deserializedObject2 = ((testObjects)objects2);
bool isObjectEquals = cmp.Equals(deserializedObject, deserializedObject2);
Console.WriteLine(string.Format("Objects are {0}", isObjectEquals ? "Equals" : "Not Equals"));
Class ObjectComparer
Inherits EqualityComparer(Of testObject)
Public Overrides Function Equals(c1 As testObject, c2 As testObject) As Boolean
If c1.name = c2.name AndAlso c1.column = c2.column AndAlso c1.enumName = c2.enumName AndAlso c1.type = c2.type Then
Return True
Else
Return False
End If
End Function
Public Overrides Function GetHashCode(c As testObject) As Integer
Dim hash As Integer = 23
If c.name IsNot Nothing Then
hash = hash * 37 + c.name.GetHashCode()
End If
If c.column IsNot Nothing Then
hash = hash * 37 + c.column.GetHashCode()
End If
If c.enumName IsNot Nothing Then
hash = hash * 37 + c.enumName.GetHashCode()
End If
If c.type IsNot Nothing Then
hash = hash * 37 + c.type.GetHashCode()
End If
Return hash
End Function
End Class
Class ObjectComparer2
Inherits EqualityComparer(Of testObjects)
Public Overrides Function Equals(c1 As testObjects, c2 As testObjects) As Boolean
Dim cmp As New ObjectComparer()
For Each obj1 As testObject In c1.attrs
If Not c2.attrs.Any(Function(x) cmp.Equals(x, obj1)) Then
Return False
End If
Next
Return True
End Function
Public Overrides Function GetHashCode(c As testObjects) As Integer
Dim hash As Integer = 23
For Each obj As testObject In c.attrs
hash += obj.GetHashCode()
Next
Return hash
End Function
End Class

Related

Add lambda to predicate - VB.NET

I have the above code :
if (i=0)
pred = (Function(d) d.n_pratica = n_pratica)
else
pred = (Function(d) d.n_polizza = n_polizza)
i need to add to pred another lambda expression to the one that just exists :
(Function(d) d.n_anagrafico = n_anagrafico) //this function is in another if statement so i can't add it directly to the stametent wrote before.
So if i=0
the result need to be
pred = (Function(d) d.n_pratica = n_pratica andalso d.n_anagrafico = n_anagrafico)
else
pred = (Function(d) d.n_polizza= n_polizza andalso d.n_anagrafico = n_anagrafico)
"Pred" is a Func (of object , boolean).
Thanks
This code should help:
Sub Main
Dim n_pratica As String = "Foo"
Dim n_anagrafico As String = "Bar"
Dim pred As Func(Of SomeClass, Boolean) = Function (d) d.n_pratica = n_pratica
Dim pred_original = pred
pred = Function (d) pred_original(d) AndAlso d.n_anagrafico = n_anagrafico
Dim sc = New SomeClass()
sc.n_pratica = n_pratica
sc.n_anagrafico = n_anagrafico
Console.WriteLine(pred(sc))
sc.n_pratica = "Qaz"
Console.WriteLine(pred(sc))
End Sub
Public Class SomeClass
Public n_pratica As String
Public n_anagrafico As String
End Class
It outputs True then False.
As a word of advice - please ensure that you always have Option Strict On for all of your VB coding.

ComboBox FindString Contains

I have such entries in Winforms ComboBox:
Font 8 pt
Font 9 pt
Font 10 pt
Font 12 pt
Font 14 pt
Then I have search string " 9 ".
Is here native way to find index by search string without looping?
I try this:
Dim a As Integer = myComboBox.FindString(" 9 ", 0)
... but without good result.
First, no, there is no available method in the framework that searches for sub-string in combobox items and returns the index of the first item which contains the search parameter.
But even ComboBox.FindString uses a loop as you can see in the source.
So there is nothing bad in using one, you could write an extension method for this:
public static class ControlExtensions
{
public static int FindSubStringIndex(this ComboBox combo, string subString, StringComparison comparer = StringComparison.CurrentCulture)
{
// Sanity check parameters
if(combo == null) throw new ArgumentNullException("combo");
if (subString == null) {
return -1;
}
for (int index = 0; index < combo.Items.Count; index++)
{
object obj = combo.Items[index];
if(obj == null) continue;
string item = Convert.ToString(obj, CultureInfo.CurrentCulture);
if (string.IsNullOrWhiteSpace(item) && string.IsNullOrWhiteSpace(subString))
return index;
int indexInItem = item.IndexOf(subString, comparer);
if (indexInItem >= 0)
return index;
}
return -1;
}
}
Now you can use it in this way:
int index = combo.FindSubStringIndex("9");
Whoops, VB.NET:
Public Module ControlExtensions
<System.Runtime.CompilerServices.Extension> _
Public Function FindSubStringIndex(combo As ComboBox, subString As String, Optional comparer As StringComparison = StringComparison.CurrentCulture) As Integer
' Sanity check parameters
If combo Is Nothing Then
Throw New ArgumentNullException("combo")
End If
If subString Is Nothing Then
Return -1
End If
For index As Integer = 0 To combo.Items.Count - 1
Dim obj As Object = combo.Items(index)
If obj Is Nothing Then
Continue For
End If
Dim item As String = Convert.ToString(obj, CultureInfo.CurrentCulture)
If String.IsNullOrWhiteSpace(item) AndAlso String.IsNullOrWhiteSpace(subString) Then
Return index
End If
Dim indexInItem As Integer = item.IndexOf(subString, comparer)
If indexInItem >= 0 Then
Return index
End If
Next
Return -1
End Function
End Module

How to I fix my deserialize error?

Why, hello everyone!
I've got this program i've been working on for months. Basic back story of it is, its supposed to be able to transport and install applications for windows in the background, like iCloud does for apps!
Anywho, i'm using a serialize/deserialize method to save the properties (eg admin username and passwordhash, directories, ports, etc.).
I have a class called 'PropertyNest' representing the properties and links to memory allocations. I'll cut it down to only the parts that the XMLSerializer looks at and saves.
Public Class PropertyNest
'Huge bunch of functions that we dont need to look at
'#######################
Public _wasLoadedFromFile As Boolean = False
Private _port As Integer = 201
Private _httpPort As Integer = 202
Private _rootFolder As String = "\appstreamRoot"
Private _adminUser As String = "Admin"
Private _adminPass As String = "21232F297A57A5A743894A0E4A801FC3" 'admin
Private _appstreamServerType As appStreamServerType = appStreamServerType.http
Private _useDES3forserver As Boolean = True
Private _encDES3pswd As String = "21232F297A57A5A743894A0E4A801FC3" 'admin
'Properties and descriptors for 'PropertyGrid' object go here \|/
'=================================================================
End Class
And its declared in the main window, serverMain like this,
Public Shared Property_Nest As AdvancedSettings.PropertyNest
and initialized later in like this,
If settingsfilename = "" Then
Property_Nest = New AdvancedSettings.PropertyNest()
Else
If propFileEncrypted = False Then
WriteLog("From unprotected file...", False)
Try
Property_Nest = AdvancedSettings.PropertyNest.LoadFrom(settingsfilename)
Catch ex As Exception
WriteLog("FAILED! Making default property nest...")
Property_Nest = New AdvancedSettings.PropertyNest()
End Try
Else
WriteLog("From encrypted file...", False)
Try
Property_Nest = AdvancedSettings.PropertyNest.LoadFrom(settingsfilename, True, propFilePswd)
Catch ex As Exception
WriteLog("FAILED! Making default property nest...", False)
Property_Nest = New AdvancedSettings.PropertyNest()
End Try
End If
End If
Thats all well and good. Loading it from the file that its saved to is the problem. Inside the PropertyNest class, I have 2 serializers programmed like so:
(Sorry its a bunch, there's optional encrypting of the serialized products with TrippleDES)
Public Sub SaveAs(ByVal filename As String, Optional ByVal Encrypted As Boolean = False)
Dim extra As String
If Encrypted = True Then : extra = "Encrypted? : Yes." : Else : extra = "Encrypted? : No."
End If
If filename = Nothing Then
Exit Sub
End If
writeLog2("Saving Property Nest to: " & filename & vbCrLf & extra, False)
If Encrypted = False Then
Dim writer As New Xml.Serialization.XmlSerializer(GetType(PropertyNest))
Dim file As New System.IO.StreamWriter(filename)
writer.Serialize(file, Me)
file.Close()
Else
Dim writer As New Xml.Serialization.XmlSerializer(GetType(PropertyNest))
Dim memstream As New System.IO.MemoryStream
writer.Serialize(memstream, Me)
memstream.Seek(0, IO.SeekOrigin.Begin)
Dim file As New System.IO.StreamWriter(filename)
Dim memstreamReader As New System.IO.StreamReader(memstream)
Do
file.WriteLine(serverMain.admin_des3Manager.Encrypt(memstreamReader.ReadLine()))
Loop Until memstreamReader.EndOfStream = True
file.Close()
End If
writeLog2("OK!")
End Sub
Shared Function LoadFrom(ByVal filename As String, Optional ByVal EncryptedWithPswd As Boolean = False, Optional ByVal Password As String = "") As PropertyNest
Dim reader As New Xml.Serialization.XmlSerializer(GetType(PropertyNest))
Dim file As New System.IO.StreamReader(filename)
Dim newPropNest As PropertyNest
If EncryptedWithPswd = False Then
newPropNest = reader.Deserialize(file) 'Error in XML Document(11, 3)
Else
If Password = "" Then
Dim convertedStream As New System.IO.MemoryStream
Dim convertedWriter As New System.IO.StreamWriter(convertedStream)
Do
convertedWriter.WriteLine(serverMain.admin_des3Manager.Decrypt(file.ReadLine()))
Loop Until file.EndOfStream = True
convertedWriter.Close()
newPropNest = reader.Deserialize(convertedStream)
Else
Dim tempDES3 As New DES3(Password)
Dim convertedStream As New System.IO.MemoryStream
Dim convertedWriter As New System.IO.StreamWriter(convertedStream)
Do
convertedWriter.WriteLine(tempDES3.Decrypt(file.ReadLine()))
Loop Until file.EndOfStream = True
convertedWriter.Close()
newPropNest = reader.Deserialize(convertedStream)
End If
End If
Return newPropNest
End Function
I marked the error in there.
Phew. Almost done.
i'm only worried about unencrypted right now, so i did my duty to save a custom, non default property nest, and it wrote to the file like so:
<?xml version="1.0" encoding="utf-8"?>
<PropertyNest xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<_wasLoadedFromFile>false</_wasLoadedFromFile>
<ServerPort>2010</ServerPort>
<AdminUser>Matthew</AdminUser>
<AdminPasswordHash>21232F297A57A5A743894A0E4A801FC3</AdminPasswordHash>
<AppStreamPort>2020</AppStreamPort>
<AppStream_ServerRoot>\appstreamRoot</AppStream_ServerRoot>
<UseDES3>true</UseDES3>
<EncDES3Pswd>21232F297A57A5A743894A0E4A801FC3</EncDES3Pswd>
</PropertyNest>
Awesome! now.... If you look at the 'LoadFrom' function, you'll see i commented the line where i get the error... I dont see an error at 11, 3. Please help!
Thanks so much :D
Your XML is valid, however the class you need to deserialise, should be like this according to visual studio, copy you XML to the clipboard, go to the edit menu, paste special and past XML as classes give you this, give it a try see if it works, you can use a c# to vb converter to change to VB if you need to.
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
public partial class PropertyNest
{
private bool _wasLoadedFromFileField;
private ushort serverPortField;
private string adminUserField;
private string adminPasswordHashField;
private ushort appStreamPortField;
private string appStream_ServerRootField;
private bool useDES3Field;
private string encDES3PswdField;
/// <remarks/>
public bool _wasLoadedFromFile
{
get
{
return this._wasLoadedFromFileField;
}
set
{
this._wasLoadedFromFileField = value;
}
}
/// <remarks/>
public ushort ServerPort
{
get
{
return this.serverPortField;
}
set
{
this.serverPortField = value;
}
}
/// <remarks/>
public string AdminUser
{
get
{
return this.adminUserField;
}
set
{
this.adminUserField = value;
}
}
/// <remarks/>
public string AdminPasswordHash
{
get
{
return this.adminPasswordHashField;
}
set
{
this.adminPasswordHashField = value;
}
}
/// <remarks/>
public ushort AppStreamPort
{
get
{
return this.appStreamPortField;
}
set
{
this.appStreamPortField = value;
}
}
/// <remarks/>
public string AppStream_ServerRoot
{
get
{
return this.appStream_ServerRootField;
}
set
{
this.appStream_ServerRootField = value;
}
}
/// <remarks/>
public bool UseDES3
{
get
{
return this.useDES3Field;
}
set
{
this.useDES3Field = value;
}
}
/// <remarks/>
public string EncDES3Pswd
{
get
{
return this.encDES3PswdField;
}
set
{
this.encDES3PswdField = value;
}
}
}

VB.NET - Extracting text inside quotation in a complex string

I have a string looking like this:
a:391:i:0;s:12:"jnKKPkvpNnfn";i:1;s:12:"ic9VAk3PvQ3j";i:2;s:12:"PEBFuE6bGepr";i:3;s:12:"bwuxRkH6QbGp";i:4;s:12:"LSRDQbAKXc9q";i:5;s:12:"eLuVbSAxQCgo";}
And I want to get the text inside the quotations and send them to a listbox.
I know sort of how to do it, but in an ineffective way that might now work... So I'm asking for advice with an example on how to do it.
Thanks
This should get you started; the method will run through an input string and return an array of strings that are contained within quotes.
string[] ParseQuotes(string input)
{
List<string> matches = new List<string>();
bool open = false;
int index = -1;
for (int i = 0; i < input.Length; i++)
{
if (input[i] == '"')
{
if (!open)
{
open = true;
index = i;
}
else
{
open = false;
string match = input.Substring(index + 1, index - i - 1);
matches.Add(match);
}
}
}
return matches.ToArray();
}
Converted to VB...
Private Function ParseQuotes(input As String) As String()
Dim matches As New List(Of String)()
Dim open As Boolean = False
Dim index As Integer = -1
For i As Integer = 0 To input.Length - 1
If input(i) = """"C Then
If Not open Then
open = True
index = i
Else
open = False
Dim match As String = input.Substring(index + 1, index - i - 1)
matches.Add(match)
End If
End If
Next
Return matches.ToArray()
End Function
In your main code:
cbYourcomboBox.Items.Clear()
cbYourcomboBox.Items.AddRange(GetList(str).ToArray)
and then the function itself:
Public Function GetList(ByVal str As String) As List(Of String)
Dim ar As String()
Dim ar2 As List(Of String) = New List(Of String)
ar = Split(str, Chr(34))
' making sure there is a matching closing quote with - (UBound(ar) And 1)
For a As Integer = 1 To UBound(ar) - (UBound(ar) And 1) Step 2
ar2.Add(ar(a))
Next a
Return ar2
End Function

how to sort list with strings containing numbers?

I have a Tlist that contains addresses. When I sort the list, numbers in the address are considered a string, and it doesn't sort correctly. How should I sort the list ascending?
Dim sortme As List(Of data) = tempdata 'main list containing addresses as strings.
sortme.Sort(Function(p1 As data, p2 As data) numorder(p1.Value).CompareTo(numorder(p2.Value)))
Private Function numorder(ByVal str As String)
Try
Dim words() As String = str.Split(" "c) 'read string up to first space (for number)
Return Convert.ToInt32(words(0))
Catch ex As Exception
End Try
End Function
Example of current output:
1001 street name
103 street name
1021 street name
It should be:
103 street name
1001 street name
1021 street name
The idea is to write your own comparer which will firs consider the number prefix and then the string itself. This comparer can be then used anywhere, for instance in LINQ OrderBy(). Here an example in c# see full VB.NET version below.
public class StreetComparer : IComparer<string>
{
public int Compare(string x, string y)
{
int indexOfSpaceX = x.IndexOf(' ');
string numericalPartX = x.Substring(0, indexOfSpaceX);
int indexOfSpaceY = y.IndexOf(' ');
string numericalPartY = y.Substring(0, indexOfSpaceY);
int numberX;
int numberY;
if(!int.TryParse(numericalPartX, out numberX) ||
!int.TryParse(numericalPartY, out numberY))
{
//Some code to handle the case where number is missing
throw new ArgumentException();
}
if (numberX!=numberY)
{
return numberX-numberY;
}
string textPartX = x.Substring(indexOfSpaceX + 1);
string textPartY = x.Substring(indexOfSpaceY + 1);
return String.Compare(textPartX, textPartY, true, CultureInfo.CurrentCulture);
}
}
class Program
{
static void Main(string[] args)
{
var myStreets = new[] {"01 aaa", "02 bbb"};
var result = myStreets.OrderBy(s => s, new StreetComparer());
}
}
Now a VB.NET version adapted exactly to your use case a List with classes sorted by property:
Public Class StreetComparer
Implements IComparer(Of String)
Public Function Compare(x As String, y As String) As Integer
Dim indexOfSpaceX As Integer = x.IndexOf(" "C)
Dim numericalPartX As String = x.Substring(0, indexOfSpaceX)
Dim indexOfSpaceY As Integer = y.IndexOf(" "C)
Dim numericalPartY As String = y.Substring(0, indexOfSpaceY)
Dim numberX As Integer
Dim numberY As Integer
If Not Integer.TryParse(numericalPartX, numberX) OrElse Not Integer.TryParse(numericalPartY, numberY) Then
'Some code to handle the case where number is missing
Throw New ArgumentException()
End If
If numberX <> numberY Then
Return numberX - numberY
End If
Dim textPartX As String = x.Substring(indexOfSpaceX + 1)
Dim textPartY As String = x.Substring(indexOfSpaceY + 1)
Return [String].Compare(textPartX, textPartY, True, CultureInfo.CurrentCulture)
End Function
End Class
Public Class Person
Public Property Value() As String
Get
Return m_Value
End Get
Set
m_Value = Value
End Set
End Property
Private m_Value As String
Public Sub New(value__1 As String)
Value = value__1
End Sub
End Class
Class Program
Private Shared Sub Main(args As String())
Dim sortme As New List(Of Person)(New () {New Person("1001 street name"), New Person("103 street name"), New Person("1021 street name")})
Dim result = sortme.OrderBy(Function(p) p.Value, New StreetComparer())
For Each person As var In result
Console.WriteLine(person.Value)
Next
Console.ReadKey()
End Sub
End Class