Any reason why hidden has no bearing on ConvertTo-Json? Seems that Get-Member honors visibility, but JSON serialization does not.
Class Person {
hidden [string] $FirstName
hidden [string] $LastName
[string] $FullName
Person([string]$First, [string]$Last) {
$this.FirstName = $First
$this.LastName = $Last
$this.FullName = $First, $Last -join " "
}
[string] ToString() {
Return $this.FullName
}
}
$jDoe = [Person]::new("John", "Doe")
Write-Output "`nProperties:"
$jDoe | Get-Member -MemberType "Property" | Format-Table "Name", "MemberType"
Write-Output "`nJSON:"
$jDoe | ConvertTo-Json
Properties:
Name MemberType
---- ----------
FullName Property
JSON:
{
"FullName": "John Doe"
}
Properties:
Name MemberType
---- ----------
FullName Property
JSON:
{
"FirstName": "John",
"LastName": "Doe",
"FullName": "John Doe"
}
Name Value
---- -----
PSVersion 6.2.1
PSEdition Core
GitCommitId 6.2.1
OS Microsoft Windows 10.0.17134
Platform Win32NT
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
WSManStackVersion 3.0
FWIW, Appears ConvertTo-Xml -As "String" _does_ honor visibility:
<?xml version="1.0" encoding="utf-8"?>
<Objects>
<Object Type="Person">
<Property Name="FullName" Type="System.String">John Doe</Property>
</Object>
</Objects>
Also, did see #6652 and there's some mention re: hidden with regards to format-* but didn't see anythign related to JSON serialization.
/cc @markekraus I think you're probably the best person to ask about why this works this way / how we might align it more with other Convert cmdlets. 🙂
Looked quickly, appears XML uses a CustomSerialization serializer, which appears to iterate the PSObject.properties itself, which I assume implements some kind of filtering mechanism (through the PSMemberInfoIntegratingCollection<>). ConvertTo-Json, however, appears to hand it off to newtonsoft without allowing it the benefit of examining context, therefore it implicitly assembles it via reflection.
Looks like you'd have to create a ContractResolver and pass it off that context for it to work the same, at least from what I gathered from doing a preliminary. 🤷‍♂️
Someone correct me if I’m wrong but isn’t serialization/deserialization a misnomer for the Convert* cmdlets? You are never going to get a functional class back out of a “serialized” class unless it a POCO to start with. It’s something different by then in the example here.
@thezim I can appreciate that, but not looking to convert back. The example was handy given I ran into the issue, but the original intent is to use a model to build a final object. That object is then consumed by an external system, and I'd rather not expose the intermediary properties.
That said, It's still inconsistent behavior. Get-Member and Csv, Html & Xml work, so (IMHO) ConvertTo-Json should work too.
Just to affirm that the current behavior is indeed unexpected:
Select-Object (with wildcards) and ConvertTo-Csv / Export-Csv - sensibly - do _not_ include hidden properties - ConvertTo-Json should act the same.
(Export-CliXml does, but there it makes sense (as-faithful-as-possible serialization); the rarely used ConvertTo-Xml does _not_).
May be fixed in #11198 as a side effect. :-)
Most helpful comment
Someone correct me if I’m wrong but isn’t serialization/deserialization a misnomer for the Convert* cmdlets? You are never going to get a functional class back out of a “serialized” class unless it a POCO to start with. It’s something different by then in the example here.