Validate Script - Validate Custom Object Data Type

Hi All,

Attempting to do something I assumed would be straightforward but it not working as I expected. I have a simple function which accepts an array of objects, each object being a hash table (pscustomobject) of name/value pairs. Both the name and value to be of type string.

Example array can be created using:

[array]$factsArray
$factsArray += [pscustomobject]@{
name = 'name1'
value = 'value1'
}
$factsArray += [pscustomobject]@{
name = 'name2'
value = 'value2'
}

My current validate script confirms the present of the name and value property in each array element but I would also like to confirm each of these properties are strings.

I had (incorrectly) assumed it would be as simple as $array[#].property -as [string] but this does not appear to be working.

Example validate script:

function Test-ValidateScript
{
param
(
[Parameter(Mandatory = $true)]
[ValidateScript({

if(-not ($_.PSobject.Properties.name -contains 'Name'))
{
throw [System.Management.Automation.ValidationMetadataException] 'An Array Element Did Not Contain Name Property'
}

if(-not ($_.PSobject.Properties.name -contains 'Value'))
{
throw [System.Management.Automation.ValidationMetadataException] 'An Array Element Did Not Contain Value Property'
}

return $true

})]
[array]$testArrayVar
)}

 

I am not concerned with what the string is, just that it is a string.

Any suggestions appreciated.

First thing to know is every PSCustomObject property name is always a string. So really you should only be concerned with values. Here are some demonstrations

$var = [pscustomobject]@{
    [int]1=2
    string='def'
}

$var.psobject.properties | ForEach-Object {
    "Property name {0} {1} a string" -f $_.name,("is not","is")[$_.name -is [string]]
    "Property value {0} {1} a string" -f $_.name,("is not","is")[$_.value -is [string]]
}

Property name 1 is a string
Property value 1 is not a string
Property name string is a string
Property value string is a string


$var = [pscustomobject]@{
    [int]1='abc'
    string='def'
}

$var.psobject.properties | ForEach-Object {
    "Property name {0} {1} a string" -f $_.name,("is not","is")[$_.name -is [string]]
    "Property value {0} {1} a string" -f $_.name,("is not","is")[$_.value -is [string]]
}

Property name 1 is a string
Property value 1 is a string
Property name string is a string
Property value string is a string

Notice on the second example even though we tried to make it an int, it is a string and powershell had no issues forcing it to be a string.

Now hashtable keys can be different types.

$ht = @{
    [int]1=2
    string='def'
}

$ht.GetEnumerator() | ForEach-Object {
    "Hashtable key {0} is type {1}" -f $_.key,$_.key.GetType().name
    "Hashtable value {0} is type {1}" -f $_.value,$_.value.GetType().name
}

Hashtable key 1 is type Int32
Hashtable value 2 is type Int32
Hashtable key string is type String
Hashtable value def is type String


$ht = @{
    [int]1='abc'
    string='def'
}

$ht.GetEnumerator() | ForEach-Object {
    "Hashtable key {0} is type {1}" -f $_.key,$_.key.GetType().name
    "Hashtable value {0} is type {1}" -f $_.value,$_.value.GetType().name
}

Hashtable key 1 is type Int32
Hashtable value abc is type String
Hashtable key string is type String
Hashtable value def is type String

I did not know, if i get you right.

You want to check if a variable is a string or not?

Like this?

“hello” -is [string]

“hello”,“world” -is [string]

For your example, using a function for validation, it should be:

function Test-It {
    param (
        [Parameter(ValueFromPipelineByPropertyName=$true)]
        [string]$Name,
        [Parameter(ValueFromPipelineByPropertyName=$true)]
        [string]$Value
    )

    #Default\Built-in hash for passed parameters
    $PSBoundParameters

}

[pscustomobject]@{Name='Foo';Value='Faa'} | Test-It

Thanks for all the replies guys, have it working, did not realise it was as simple as GetType().Name. Tried a few methods passing the values into get-member and others but never worked this appears to.

Just to clarify some of the confusion, the script I initially posted was just an example to test getting the validation to work not the actual script itself. The input needs to be an array of name/value pairs as the actual function can accept between 0 and 50 pairs so I figured an array was best, note the array is not the only input. My goal was to validate the array being passed in as the function will be provided to colleagues and I want it to fail if each part of the array does not:

Contain a name property of type string

Contain a value property of type string

Final validation that appears to be working from initial testing is:

[ValidateScript({

if(-not ($_.PSobject.Properties.name -contains ‘name’))
{
throw [System.Management.Automation.ValidationMetadataException] ‘An Array Element Did Not Contain Name Property’
}

if($_.name.gettype().name -ne ‘string’)
{
throw [System.Management.Automation.ValidationMetadataException] ‘An Array Element Contained Name Property That Was Not String’
}

if(-not ($_.PSobject.Properties.name -contains ‘value’))
{
throw [System.Management.Automation.ValidationMetadataException] ‘An Array Element Did Not Contain Value Property’
}

if($_.value.gettype().name -ne ‘string’)
{
throw [System.Management.Automation.ValidationMetadataException] ‘An Array Element Contained Value Property That Was Not String’
}

 

return $true

})]

Thanks to all for the help

There is a function on GitHub that may help you to achieve what you want:

 

PowerShell/Get-PropertyType.ps1 at master · RamblingCookieMonster/PowerShell (github.com)