Repository: PowerShell/PowerShell
File: test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertTo-Json.Tests.ps1 (PowerShell)

Code before:

    Context 'PowerShell class basic serialization' {
        BeforeAll {
            class SimpleClass {
                [string]$Name
                [int]$Value
            }

            class ClassWithConstructor {
                [string]$Name
                [int]$Value
                ClassWithConstructor([string]$name, [int]$value) {
                    $this.Name = $name
                    $this.Value = $value
                }
            }

            class ClassWithMethod {
                [string]$Name
                [int]$Value
                [int] GetDoubled() { return $this.Value * 2 }
            }

            class ClassWithHiddenProperty {
                [string]$Name
                hidden [string]$Secret
            }
        }

        It 'Should serialize simple PowerShell class via Pipeline and InputObject' {
            $obj = [SimpleClass]@{ Name = 'Test'; Value = 42 }
            $expected = '{"Name":"Test","Value":42}'
            $jsonPipeline = $obj | ConvertTo-Json -Compress
            $jsonInputObject = ConvertTo-Json -InputObject $obj -Compress
            $jsonPipeline | Should -BeExactly $expected
            $jsonInputObject | Should -BeExactly $expected
        }

        It 'Should serialize PowerShell class with constructor via Pipeline and InputObject' {
            $obj = [ClassWithConstructor]::new('Test', 42)
            $expected = '{"Name":"Test","Value":42}'
            $jsonPipeline = $obj | ConvertTo-Json -Compress
            $jsonInputObject = ConvertTo-Json -InputObject $obj -Compress
            $jsonPipeline | Should -BeExactly $expected
            $jsonInputObject | Should -BeExactly $expected
        }

        It 'Should not serialize methods of PowerShell class via Pipeline and InputObject' {
            $obj = [ClassWithMethod]@{ Name = 'Test'; Value = 10 }
            $expected = '{"Name":"Test","Value":10}'
            $jsonPipeline = $obj | ConvertTo-Json -Compress

Review comment (suggestion):
I'd move to SimpleClass.

Really we could have all types in SimpleClass we use in tests - primitive, BigInt, Guid, IPAddress, array and dictionary with compound nested elements, and including ETS properties.

Code after:

    Context 'PowerShell class serialization' {
        BeforeAll {
            class SimpleClass {
                [string]$StringVal
                [int]$IntVal
                [bool]$BoolVal
                [double]$DoubleVal
                [bigint]$BigIntVal
                [guid]$GuidVal
                [ipaddress]$IPVal
                [object[]]$ArrayVal
                [System.Collections.Specialized.OrderedDictionary]$DictVal
                hidden [string]$HiddenVal
            }
        }

        It 'Should serialize PowerShell class with various property types including ETS via Pipeline and InputObject' {
            $obj = [SimpleClass]::new()
            $obj.StringVal = 'hello'
            $obj.IntVal = 42
            $obj.BoolVal = $true
            $obj.DoubleVal = 3.14
            $obj.BigIntVal = [bigint]::Parse('99999999999999999999')
            $obj.GuidVal = [guid]'12345678-1234-1234-1234-123456789abc'
            $obj.IPVal = [ipaddress]::Parse('192.168.1.1')
            $obj.ArrayVal = @(1, 'two', $true)
            $obj.DictVal = [ordered]@{ Key = 'Value'; Nested = [ordered]@{ Inner = 1 } }
            $obj.HiddenVal = 'secret'
            $obj | Add-Member -MemberType NoteProperty -Name ETSNote -Value 'note'
            $obj | Add-Member -MemberType ScriptProperty -Name ETSScript -Value { $this.StringVal.Length }
            $obj.IPVal | Add-Member -MemberType NoteProperty -Name Label -Value 'primary'
            $expectedPipeline = '{"StringVal":"hello","IntVal":42,"BoolVal":true,"DoubleVal":3.14,"BigIntVal":99999999999999999999,"GuidVal":"12345678-1234-1234-1234-123456789abc","IPVal":{"AddressFamily":2,"ScopeId":null,"IsIPv6Multicast":false,"IsIPv6LinkLocal":false,"IsIPv6SiteLocal":false,"IsIPv6Teredo":false,"IsIPv6UniqueLocal":false,"IsIPv4MappedToIPv6":false,"Address":16885952},"ArrayVal":[1,"two",true],"DictVal":{"Key":"Value","Nested":{"Inner":1}},"HiddenVal":"secret","ETSNote":"note","ETSScript":5}'
            $expectedInputObject = '{"StringVal":"hello","IntVal":42,"BoolVal":true,"DoubleVal":3.14,"BigIntVal":99999999999999999999,"GuidVal":"12345678-1234-1234-1234-123456789abc","IPVal":{"AddressFamily":2,"ScopeId":null,"IsIPv6Multicast":false,"IsIPv6LinkLocal":false,"IsIPv6SiteLocal":false,"IsIPv6Teredo":false,"IsIPv6UniqueLocal":false,"IsIPv4MappedToIPv6":false,"Address":16885952},"ArrayVal":[1,"two",true],"DictVal":{"Key":"Value","Nested":{"Inner":1}},"HiddenVal":"secret"}'
            $jsonPipeline = $obj | ConvertTo-Json -Compress -Depth 3
            $jsonInputObject = ConvertTo-Json -InputObject $obj -Compress -Depth 3
            $jsonPipeline | Should -BeExactly $expectedPipeline
            $jsonInputObject | Should -BeExactly $expectedInputObject
        }

        It 'Should serialize PowerShell class with default values via Pipeline and InputObject' {
            $obj = [SimpleClass]::new()
            $expected = '{"StringVal":null,"IntVal":0,"BoolVal":false,"DoubleVal":0.0,"BigIntVal":0,"GuidVal":"00000000-0000-0000-0000-000000000000","IPVal":null,"ArrayVal":null,"DictVal":null,"HiddenVal":null}'
            $jsonPipeline = $obj | ConvertTo-Json -Compress
            $jsonInputObject = ConvertTo-Json -InputObject $obj -Compress
            $jsonPipeline | Should -BeExactly $expected
            $jsonInputObject | Should -BeExactly $expected
        }
    }

    Context 'Nested PowerShell class' {