Tyler Pantuso
Tyler Pantuso

Reputation: 853

How can I use Import-CliXml to deserialize a generic list of custom class objects?

I am trying to learn XML serialization in PowerShell. So, I am making a simple contact list to serialize and deserialize. The problem I am running into is that the Contact object is acting differently when I import it with Import-CliXml.

Here is what I am trying right now:

class Contact {
[string]$FirstName;
[string]$LastName;
[Int64]$PhoneNumber; }

$bob = new-object Contact
$bob.FirstName = "Bob"
$bob.LastName = "Johnson"
$bob.PhoneNumber = 1235589876

$bill = new-object Contact
$bill.FirstName = "Bill"
$bill.LastName = "Carson"
$bill.PhoneNumber = 1235589875

$ContactList = new-object System.Collections.Generic.List[Contact]
$ContactList.Add($bob)
$ContactList.Add($bill)

[xml]$data = $ContactList | convertto-xml

new-item "C:\Users\Public\Documents\Contacts.xml"
$data | export-clixml "C:\Users\Public\Documents\Contacts.xml"

[xml]$ImportedData = import-clixml "C:\Users\Public\Documents\Contacts.xml"
$ImportedList = new-object System.Collections.Generic.List[Contact]
$ImportedList = $ImportedData.Objects.Object

The imported List[Contact] has a collection of Contact objects, but I cannot seem to get the information from their properties. For example, when I get blank lines when I try the following:

$ImportedList | foreach-object { write-host $_.FirstName }

I know the objects are there because of the return I get from $ImportedList:

$ImportedList

Type    Property
----    --------
Contact {FirstName, LastName, PhoneNumber}
Contact {FirstName, LastName, PhoneNumber}

I am trying to get it to return the same thing as $ContactList:

$ContactList

FirstName LastName PhoneNumber
--------- -------- -----------
Bob       Johnson  1235589876
Bill      Carson   1235589875

Any help would be greatly appreciated.

Upvotes: 0

Views: 1299

Answers (2)

Tyler Pantuso
Tyler Pantuso

Reputation: 853

Thank you Tav for the clear answer. This is what I ended up using:

$ImportedList = new-object System.Collections.Generic.List[Contact]

$ImportedData.Objects.Object | foreach-object {
$NewContact = new-object Contact
$NewContact.FirstName = $_.Property[0].'#text'
$NewContact.LastName = $_.Property[1].'#text'
$NewContact.PhoneNumber = [Int64]$_Property[2].'#text'
$ImportedList.Add($NewContact) }

Update

I was able to use the property names with the Where() method:

$ImportedList = new-object System.Collections.Generic.List[Contact]

$ImportedData.Objects.Object | foreach-object {
$NewContact = new-object Contact
$NewContact.FirstName = $_.Property.Where({ $_.Name -eq "FirstName" }).'#text'
$NewContact.LastName = $_.Property.Where({ $_.Name -eq "LastName" }).'#text'
$NewContact.PhoneNumber = [Int64]$_Property.Where({ $_.Name -eq "PhoneNumber" }).'#text'
$ImportedList.Add($NewContact) }

Upvotes: 0

user5635168
user5635168

Reputation:

The problem you are having is down to import-clixml, it doesn't return object type [contact]. $ImportedData.Objects.Object is instead of type [System.Xml.XmlElement] which is why you get blank lines here:

$ImportedList | foreach-object { write-host $_.FirstName }

as there is no property firstname on the object in the pipeline.

Instead of these two lines:

$ImportedList = new-object System.Collections.Generic.List[Contact]
$ImportedList = $ImportedData.Objects.Object

Try this:

$ImportedList = @()
$ImportedData.Objects.Object | %{$ImportedList += [contact]@{firstname=$_.property[0].'#text';lastname=$_.property[1].'#text';phonenumber=$_.property[2].'#text'}}

Upvotes: 1

Related Questions