Fix #242 - Adds support for PSCustomObject
PR Summary
Adds support for dealing with native PSObject instances (current code only deals with native object types).
- Extracts nested 'cached member' classes to seperate files
- Adds interface and abstract base
- Adds implementation for PSObject properties
Fixes #242
Test JSON
$Values = @'
{
"Candidate":
{
"Name": {
"3rd": "Surname",
"1st": "Forename",
"2nd": "Middle name"
},
"Date of Birth": "+1582-10-15",
"E-mail Address": "mailTo:[email protected]",
"Mobile Telephone Number": "tel:+00-0000-000000",
"Blood Group": "" // Unknown
},
"Mother":
{
"Name": {
"3rd": "Surname",
"1st": "Forename",
"2nd": "Middle name"
},
"Date of Birth": "+1582-10-15",
"E-mail Address": "mailTo:[email protected]",
"Mobile Telephone Number": "tel:+00-0000-000000",
},
"Father":
{
"Name": {
"3rd": "Surname",
"1st": "Forename",
"2nd": "Middle name"
},
"Date of Birth": "+1582-10-15",
"E-mail Address": "mailTo:[email protected]",
"Mobile Telephone Number": "tel:+00-0000-000000",
},
}
'@
Test JSON 2
Test JSON 2 loaded in Show-ObjectTree
$Values = @'
{
"name": "Root",
"value": "Root Value",
"children": [
{
"name": "Child 1",
"value": "Child 1 Value",
"children": [
{
"name": "Grandchild 1",
"value": "Grandchild 1 Value",
"children": [
{
"name": "Great-Grandchild 1",
"value": "Great-Grandchild 1 Value",
"attributes": {
"attribute1": "Value1",
"attribute2": "Value2"
},
"relatedObjects": [
{
"id": 123,
"name": "Related Object 1"
},
{
"id": 124,
"name": "Related Object 2"
}
]
},
{
"name": "Great-Grandchild 2",
"value": "Great-Grandchild 2 Value",
"attributes": {
"attribute1": "Value1",
"attribute2": "Value2"
},
"relatedObjects": [
{
"id": 125,
"name": "Related Object 3"
}
]
}
]
},
{
"name": "Grandchild 2",
"value": "Grandchild 2 Value",
"attributes": {
"attribute1": "Value1",
"attribute2": "Value2"
}
}
]
},
{
"name": "Child 2",
"value": "Child 2 Value",
"children": [
{
"name": "Grandchild 3",
"value": "Grandchild 3 Value",
"attributes": {
"attribute1": "Value1",
"attribute2": "Value2"
}
},
{
"name": "Grandchild 4",
"value": "Grandchild 4 Value",
"attributes": {
"attribute1": "Value1",
"attribute2": "Value2"
}
}
],
"arrayProperty": [1, 2, 3, 4]
},
{
"name": "Child 3",
"value": "Child 3 Value",
"attributes": {
"attribute1": "Value1",
"attribute2": "Value2"
},
"arrayProperty": ["a", "b", "c"]
}
]
}
'@
How to manually test with the above JSON
Invoke-Build Build -ModuleName Microsoft.PowerShell.ConsoleGuiTools
pwsh
import-Module ./module/Microsoft.PowerShell.ConsoleGuiTools
$Values = @'
{
...
}
'@
$Values | ConvertFrom-JSON | Show-ObjectTree
A new pwsh window is launched to avoid conflict of modules. Exit after test with exit.
PR Context
@andyleejordan this is ready for review if you are able to find time 🚀
@tznind We need to fix this in ocgv too. I haven't had a chance to look at your fix here closely, so I'm curious if you spent anytime on that?
@tznind We need to fix this in
ocgvtoo. I haven't had a chance to look at your fix here closely, so I'm curious if you spent anytime on that?
Ah, no I did not look at the ocgv command. I did create a helper though shouldn't be too hard to port across. I can probably take a look at the weekend.
@tig I have looked into the ocgv implementation and do not think it will have the same issues that the tree view had (that this PR corrects).
ocgv uses GetFormatViewDefinitionForObject and CastObjectsToTableView to deal with the input PSObject directly while tree view involves itself quite heavily in 'Root object' being wrapped by the PSObject (e.g. to handle cases like directories etc).
Both of the below look like correct behaviours to me, see example json
$Values = @'
[
{
"id": 1,
"name": "John",
"age": 30,
"city": "New York",
"people":
[
{
"name": "Alice"
},
{
"name": "Frank"
}
]
},
{
"id": 2,
"name": "Alice",
"age": 25,
"city": "Los Angeles"
},
{
"id": 3,
"name": "Bob",
"age": 35,
"city": "Chicago"
}
]
'@
You get
With tree view you get
Does this enhancement also handle the scenario of real .NET objects like FileInfo with PowerShell's ETS (Extended Type System) properties?
Here is an example with Get-ChildItem with FileInfo and DirectoryInfo.
PS C:\Users\thomas> Get-ChildItem | gm | where MemberType -notin property,method
TypeName: System.IO.DirectoryInfo
Name MemberType Definition
---- ---------- ----------
Target AliasProperty Target = LinkTarget
LinkType CodeProperty System.String LinkType{get=GetLinkType;}
Mode CodeProperty System.String Mode{get=Mode;}
ModeWithoutHardLink CodeProperty System.String ModeWithoutHardLink{get=ModeWithoutHardLink;}
ResolvedTarget CodeProperty System.String ResolvedTarget{get=ResolvedTarget;}
PSChildName NoteProperty string PSChildName=.oci
PSDrive NoteProperty PSDriveInfo PSDrive=C
PSIsContainer NoteProperty bool PSIsContainer=True
PSParentPath NoteProperty string PSParentPath=Microsoft.PowerShell.Core\FileSystem::C:\Users\thomas
PSPath NoteProperty string PSPath=Microsoft.PowerShell.Core\FileSystem::C:\Users\thomas\.oci
PSProvider NoteProperty ProviderInfo PSProvider=Microsoft.PowerShell.Core\FileSystem
BaseName ScriptProperty System.Object BaseName {get=$this.Name;}
TypeName: System.IO.FileInfo
Name MemberType Definition
---- ---------- ----------
Target AliasProperty Target = LinkTarget
LinkType CodeProperty System.String LinkType{get=GetLinkType;}
Mode CodeProperty System.String Mode{get=Mode;}
ModeWithoutHardLink CodeProperty System.String ModeWithoutHardLink{get=ModeWithoutHardLink;}
ResolvedTarget CodeProperty System.String ResolvedTarget{get=ResolvedTarget;}
PSChildName NoteProperty string PSChildName=_viminfo
PSDrive NoteProperty PSDriveInfo PSDrive=C
PSIsContainer NoteProperty bool PSIsContainer=False
PSParentPath NoteProperty string PSParentPath=Microsoft.PowerShell.Core\FileSystem::C:\Users\thomas
PSPath NoteProperty string PSPath=Microsoft.PowerShell.Core\FileSystem::C:\Users\thomas\_viminfo
PSProvider NoteProperty ProviderInfo PSProvider=Microsoft.PowerShell.Core\FileSystem
BaseName ScriptProperty System.Object BaseName {get=if ($this.Extension.Length -gt 0){$this.Name.Remove($th…
VersionInfo ScriptProperty System.Object VersionInfo {get=[System.Diagnostics.FileVersionInfo]::GetVersionInfo…
Does this enhancement also handle the scenario of real .NET objects like
FileInfowith PowerShell's ETS (Extended Type System) properties?Here is an example with
Get-ChildItemwithFileInfoandDirectoryInfo.[...]
I am not sure I fully understand the question. But I think the answer is yes.
The default operating proceedure for the tree view is to look for a real .NET object and enumerate its properties as leaves/branches. For example PS D:\Repos\GraphicalTools> Get-ChildItem | shot
piping get children to tree view
Note that in the case of DirectoryInfo the sub folders are also listed after properties.
However calling gm would flatten the tree which would not be helpful, so calling Get-ChildItem | gm | where MemberType -notin property,method | shot just lists the member definitions:
piping gm output is not particularly helpful
Any plans on merging this?
Bumping this, are there any plans to merge this in?