Controlling case in PowerShell JSON serialization

Controlling case in PowerShell JSON serialization
Photo by rolf neumann / Unsplash
This method only works for PowerShell classes and not for Hashtables, or PSCustomObject objects

Ever wanted to take a PowerShell object that uses the PascalCase property names that PowerShell typically uses, and convert it to JSON using snake case or camel case?

Quick Review of Cases

In programming there's many ways to use multiple words when naming items (functions, variables, etc.). The most common cases used are:

  • Pascal Case - Capitalize the first letter of each word: MyAwesomeVariable = 42
  • Camel Case - Like Pascal Case, but lowercase the first word: myAwesomeVariable = 42
  • Snake Case - Separate each word with an underscore: my_awesome_variable = 42
    • You can also use an upper variant: MY_AWESOME_VARIABLE = 42

PowerShell JSON Serialization

When PowerShell serializes an object to JSON, the property names in the JSON will match the case of the source object:

#> @{MyValue = 42; other_value = 34} | ConvertTo-Json
{
  "MyValue": 42,
  "other_value": 34
}

What if you wanted to build an object that uses Pascal Case properties like PowerShell typically uses, but then serialize it with a different case, though?

Controlling case in JSON serialization

Start by creating a PowerShell class for your data:

class SyncSession {
  [ValidateNotNullOrEmpty()][string]$ShareFolder
  [ValidateNotNullOrEmpty()][string]$RemotePath="/"
  [ValidateNotNullOrEmpty()][string]$LocalPath
}

$Session = [SyncSession]@{
  ShareFolder = "Home"
  LocalPath = "C:\Home"
}

Then, so long as are running on PowerShell 7+, we can use JSON serialization commands that are part of .NET 8 to serialize the hash table to JSON with snake case property names:

#> $JsonOptions = [System.Text.Json.JsonSerializerOptions]@{
     PropertyNamingPolicy = [System.Text.Json.JsonNamingPolicy]::SnakeCaseLower
   }

#> [System.Text.Json.JsonSerializer]::Serialize($Session, $JsonOptions)

{"share_folder":"home","remote_path":"/","local_path":"${home}\\SynologyDrive\\Home"}

Full Code

class SyncSession {
  [ValidateNotNullOrEmpty()][string]$ShareFolder
  [ValidateNotNullOrEmpty()][string]$RemotePath="/"
  [ValidateNotNullOrEmpty()][string]$LocalPath
  
  [string] ToJson() {
    $JsonOptions = [System.Text.Json.JsonSerializerOptions]@{
      PropertyNamingPolicy = [System.Text.Json.JsonNamingPolicy]::SnakeCaseLower
    }
    return [System.Text.Json.JsonSerializer]::Serialize($this, $JsonOptions)
  }
}

$Session = [SyncSession]@{
  ShareFolder = "Home"
  LocalPath = "C:\Home"
}


Write-Host $Session.ToJson()