How to Stop powershell form Converting the variable assigment of a boolean to Uppercase letter

1.4k Views Asked by At

I am trying to format a json and do dynamic variable assignment but once the boolean value is assigned powershell is changing the casetype for the first letter to uppercase. I still want to maintain the case type for my input values both lowercase and uppercase as it is in my json file.

Any help?

      {

          "input": true,
          "variable": "Relative path",
       }

  $path= "L:\test\parameter.json"
  $json = Get-Content $path | ConvertFrom-Json
  foreach ($data in $json.PSObject.Properties) { New-Variable -name $($data.name) -value $($data.value) -Force}
  
  echo $input
  True   ->>> I want it to be "true" and the value of variable to still be "Relative Path"
1

There are 1 best solutions below

0
On BEST ANSWER

Generally, you mustn't use $input as a custom variable, because it is an automatic variable managed by PowerShell.

Leaving that aside, ConvertFrom-Json converts a true JSON value - a Boolean - into the equivalent .NET Boolean (System.Boolean, represented as [bool] in PowerShell). The representation of this value in PowerShell is $true.

Printing this value to the console (host) effectively calls its .ToString() method in order to obtain a string representation, and that string representation happens to start with an uppercase letter:

PS> $true
True 

If you need an all-lowercase representation, call .ToString().ToLower(), or, for brevity, use an expandable string and call .ToLower() on it:

PS> "$true".ToLower() # In this case, the same as $true.ToString().ToLower()
true

If you want to apply the all-lowercase representation automatically to all Booleans, you have two options:

  • Modify the data, by replacing the Boolean values with their desired string representations:

    • This answer shows how to walk a [pscustomobject] object graph returned by ConvertFrom-Json and update its (leaf) properties.
  • Preferably, only modify the display formatting of [bool] values, without needing to modify the data, as zett42 suggests.

    • See below.

(Temporarily) overriding the .ToString() method of type [bool]:

Update-TypeData can be used to override the members of arbitrary .NET types, but there is a limitation due to a bug - reported in GitHub issue #14561 - present up to at least PowerShell 7.2.2:

  • A .ToString() override is not honored when you cast an instance to [string] (e.g., [string] $true) or when you use it in an expandable string (e.g, "$true")

However, with implicit stringification of Booleans, as happens during for-display formatting, it does work:

# Override the .ToString() method of [bool] (System.Boolean) instances:
# Save preexisting type data, if any.
$prevTypeData = Get-TypeData -TypeName System.Boolean
# Add a ScriptMethod member named 'ToString' that outputs an
# all-lowercase representation of the instance at hand. ('true' or 'false')
Update-TypeData -TypeName System.Boolean `
                -MemberType ScriptMethod -MemberName ToString `
                -Value { if ($this) { 'true' } else { 'false' } } `
                -Force

# Output a sample custom object with two Boolean properties.
[pscustomobject] @{ 
  TrueValue = $true
  FalseValue = $false
}

# Restore the original behavior:
# Note: In production code, it's best to put this in the `finally`
#       block of try / catch / finally statement.
# Remove the override again...
Remove-TypeData -TypeName System.Boolean
# ... and restore the previous data, if any.
if ($prevTypeData) { Update-TypeData -TypeData $prevTypeData }

Note: You cannot scope Update-TypeData calls, which invariably take effect session-globally, so it's best to remove the override again with Remove-TypeData and restore any preexisting type data, if any, as shown above.

  • zett42 has generalized the approach above to create a general-purpose
    Invoke-WithTemporaryTypeData function that scopes type-data modifications to a given piece of code (script block): see this Gist.

Output (note the all-lowercase property values):

TrueValue FalseValue
--------- ----------
     true      false