Skip to content

Instantly share code, notes, and snippets.

@ninmonkey
Last active April 20, 2025 21:06
Show Gist options
  • Save ninmonkey/032df78920dee3370d57b827d841e59e to your computer and use it in GitHub Desktop.
Save ninmonkey/032df78920dee3370d57b827d841e59e to your computer and use it in GitHub Desktop.
AutoJson.Basic-Text.Json.md

Docs

This isn't an example of what you should do, it's testing what you can do

Notes:

  • You can call [Text.Json.JsonSerializer]::Serialize on a pwsh class, using the custom type name.

  • Objects Like [Diagnostics.Process] have many properties you do not want to serialize like Modules. Instead of ConvertTo-Json -Depth 1 You can apply one of the Json Attributes

  • You can conditionally ignore keys that might emit null values, like: [JsonIgnoreAttribute( Condition = [JsonIgnoreCondition]::WhenWritingNull ) ]

#Requires -Version 7
using namespace System.Collections.Generic
using namespace System.Text
using namespace System.Text.Json
using namespace System.Text.Json.Serialization
using namespace System.Linq
$assembly = Add-type -AssemblyName System.Text.Json -PassThru -ea 'stop'
<#
This isn't an example of what you should do, it's testing what you can do
Notes:
- You can call [Text.Json.JsonSerializer]::Serialize
on a pwsh class, using the custom type name.
- Objects Like [Diagnostics.Process] have many properties
you do not want to serialize like 'Modules'.
Instead of ConvertTo-Json -Depth1, You can apply one of the Json Attributes
- You can conditionally ignore keys that might emit null values, like:
[JsonIgnoreAttribute( Condition = [JsonIgnoreCondition]::WhenWritingNull ) ]
#>
function AutoJson {
<#
.SYNOPSIS
Calls [Text.Json.JsonSerializer] using a pwsh class name
.notes
[System.Text.Json.JsonSerializer] has a ton of overloads
.LINK
https://docs.microsoft.com/en-us/dotnet/api/system.text.json.jsonserializer?view=net-8.0#methods
#>
[CmdletBinding()]
param(
[Parameter(ValueFromPipeline)]
[Alias('InObj')] [object] $Object,
# Without a type, it falls back to GetType()
[Alias('Tinfo')] [type] $TypeInfo
)
process {
if( -not $TypeInfo ) { $TypeInfo = $Object.GetType() }
[Text.Json.JsonSerializer]::Serialize( <# value: #> $Object, <# tinfo #> $TypeInfo )
'AutoJson: TryConvert type: {0}' -f $TypeInfo | Write-verbose
}
}
class SomePS {
[string] $ProcessName
[int] $Id
# [example kind 1]: Property on instances to include, but, never serialize it
[Serialization.JsonIgnoreAttribute()]
[Diagnostics.ProcessModuleCollection] $Modules
# [example kind 2]: Serialize property if it's not null, but ignore it if it's null
# note: It does not work here because [object][string]::empty is not null
[JsonIgnoreAttribute( Condition = [JsonIgnoreCondition]::WhenWritingNull ) ]
[object] $MainWindowTitle
SomePS ( [object]$Other ) {
$WantedProps = [Linq.Enumerable]::Intersect( # because linq is fun
[string[]] $This.PSObject.Properties.Name,
[string[]] $Other.PSObject.Properties.Name )
foreach($PropName in $WantedProps) {
$This.$PropName = $Other.$PropName
}
# hard coded version:
# $This.ProcessName = $Other.ProcessName
# $This.Id = $Other.Id
# $this.MainWindowTitle = $Other.MainWindowTitle
# $This.Modules = $Other.Module
}
}
$ps ??= Get-Process
$hasModules = $ps | ? Modules | Select-Object -First 4
$hasTitle = $ps | ? MainWindowTitle | Select-Object -first 4
$noTitle = $ps | ? -Not MainWindowTitle | Select-Object -first 4
'Start:' | Write-Host -fore blue
# [a] works
$hasModules -as [SomePS[]]
<# Out:
ProcessName Id Modules
----------- -- -------
ApplicationFrameHost 19636 {System.Diagnostics.ProcessModule (ApplicationFrameHost.exe), System.Diagnost ....
#>
$hasModules -as [SomePS[]] | %{ AutoJson -InObj $_ -TypeInfo ([SomePS]) }
<# Out:
{"ProcessName":"ApplicationFrameHost","Id":19636}
#>
return
# cool, typedata is constrained to derived types
{
$hasModules -as [SomePS[]] | %{ AutoJson -InObj $_ -TypeInfo ([System.Diagnostics.Process]) }
} | Should -Throw -because 'Typedef used did not derive from type'
<# Out:
Exception calling "Serialize" with "2" argument(s): "The specified
type [System.Diagnostics.Process] must derive from the specific value's type [SomePS]."
#>
$hasTitle -as [SomePs[]] | %{ AutoJson -InObj $_ }
$hasModules, $hasTitle, $noTitle -as [SomePs[]]
| AutoJson
<# Outputs:
{"ProcessName":"ApplicationFrameHost","Id":19636,"MainWindowTitle":"Snip \u0026 Sketch"}
{"ProcessName":"AggregatorHost","Id":9268,"MainWindowTitle":""}
#>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment