Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #242 - Adds support for PSCustomObject #243

Open
wants to merge 10 commits into
base: main
Choose a base branch
from

Conversation

tznind
Copy link
Contributor

@tznind tznind commented Mar 17, 2024

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:address@domain.TLD",
		"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:address@domain.TLD",
		"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:address@domain.TLD",
		"Mobile Telephone Number": "tel:+00-0000-000000",
	},
}
'@
Test JSON 2

image
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.

jsontree

PR Context

@tznind tznind marked this pull request as ready for review March 18, 2024 06:35
@tznind
Copy link
Contributor Author

tznind commented Mar 24, 2024

@andyleejordan this is ready for review if you are able to find time 🚀

@tig
Copy link
Collaborator

tig commented Mar 25, 2024

@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
Copy link
Contributor Author

tznind commented Mar 25, 2024

@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?

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.

@tznind
Copy link
Contributor Author

tznind commented Mar 30, 2024

@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
image

With tree view you get
image

@ThomasNieto
Copy link

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…

@tznind
Copy link
Contributor Author

tznind commented Apr 3, 2024

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.

[...]

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

image
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:

image
piping gm output is not particularly helpful

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Show-ObjectTree does not enumerate object data from PSObject converted from JSON via ConvertFrom-JSON.
3 participants