I have a PSCustomObject $bigObject coming imported from this JSON:
{
"psco": {
"somekey1": "somevalue",
"somekey2": "somevalue"
},
"array": [
"someitem1",
"someitem2"
]
}
psco.getType() --> PSCustomObject
array.getType() --> Object[]
as expected.
Now, if I serialize and deserialize the whole object, with [System.Management.Automation.PSSerializer], the resulting object type change to:
psco.getType() --> PSCustomObject
array.getType() --> System.Collection.ArrayList
Because this ($bigObject.array -is [PSCustomObject])
returns false before serialization (good) and false (bad) after deserialization.
Thank you!
Name Value
---- -----
PSVersion 6.2.3
PSEdition Core
GitCommitId 6.2.3
OS Microsoft Windows 10.0.18363
Platform Win32NT
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0鈥
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
WSManStackVersion 3.0
As a non-PS team member that seems normal to me, you can try using the -AsHashTable parameter since your on PSCore if you want something more consistent.
It definitely seems odd to me that an array is being deserialized to a much more complex and heavy type instead of just being emitted as an array.
The JSON serialization seems correct... the PSSerializer is what's used in the CliXML cmdlets, isn't it? That should definitely be maintaining the original type.
Is this type change to be expected or is it a bug?
The serialization infrastructure preserves type fidelity only for a relatively small number of known types (but always records the full, original type name and that of the types in its inheritance hierarchy).
List-like data structures (collections) are serialized as abstract <LST> elements, as described in Contents of Known Containers in the MS-PSRP spec.
On deserializing, the various collection types serialized as <LST> are seemingly _all_ deserialized as [System.Collections.ArrayList] instances.
While there are definitely many cases where type-faithful deserialization _isn't_ possible, you definitely _could_ faithfully "rehydrate" instances of type [object[]] (and, obviously, [System.Collections.ArrayList] itself, as well as - depending on the specific element type - [System.Collections.Generic.List[object]]).
It is unclear to me why the deserialize-all-lists-to-ArrayList approach was chosen (other than for implementation convenience), though, pragmatically speaking, it probably won't be a problem in practice too often.
Is it also to be expected that the ArrayList is considered equal to a PSCustomObject
The short of it is that you shouldn't test for custom objects with -is [pscustomobject], because it is effectively the same as -is [psobject] (see #4344) and that can _situationally_ return $true for _any_ data type instance that happens to be wrapped in an extra, otherwise invisible [psobject] instance, as in your case - see #5579.
Instead, obscurely, you must use -is [System.Management.Automation.PSCustomObject], which only returns true for true custom objects.
The caveat is that the -as variant does _not_ work - see #4343.
@mklement0 that is great info! Thank you!