Powershell: Class hidden properties still serialized to JSON

Created on 6 Jun 2019  Â·  6Comments  Â·  Source: PowerShell/PowerShell

Any reason why hidden has no bearing on ConvertTo-Json? Seems that Get-Member honors visibility, but JSON serialization does not.

Steps to reproduce

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

Expected behavior

Properties:

Name     MemberType
----     ----------
FullName   Property


JSON:
{
  "FullName": "John Doe"
}

Actual behavior

Properties:

Name     MemberType
----     ----------
FullName   Property


JSON:
{
  "FirstName": "John",
  "LastName": "Doe",
  "FullName": "John Doe"
}

Environment data

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.

Issue-Question WG-Engine

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.

All 6 comments

/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. :-)

Was this page helpful?
0 / 5 - 0 ratings