I'm using a datacontext in my powershell app (a first for me) and from what I can tell all datacontext properties and values are set with JSON and all values are strings. Example:
$DataObject = ConvertFrom-Json @"
{
"myproperty":"false"
}
But I'm having an issue where that false up there is not always evaluation to false. When I bind a control's enable property to myproperty, it properly disables as it's set to false.
But if I try to evaluate that property as a bool, it returns true:
If($state.myproperty){$true} Else {$false}
True
I don't understand why it registers as a boolean false, for purposes of the control, but I cannot reference it as such in code.
Please school me on what I'm missing.
EDIT I've come to understand Powershell will register any string over 0 characters as true. However, I'm still curious as to why when bound to a control property, this doesn't seem to be an issue.
EDIT2 I worked around this by not actually setting a default value in the JSON and simply setting the $state.myproperty to $false near the beginning of the script and set it to $true when my condition required.
Again still curious as to why the control binding properly evaluates the string "false". Also if I wanted to initialize this in JSON, can you do so without use of quotes? E.g. "myproperty":false ?
On the JSON side:
false
and true
- note the absence of quoting - are Boolean JSON values that represent the values their names imply.
By contrast, "false"
and "true"
are JSON strings whose value happens to be false
and true
, respectively - a string value has no intrinsic meaning, except by convention that the consumer of a JSON document must be aware of.
ConvertTo-Json
and ConvertFrom-Json
use specially formatted strings such as "2022-06-27T15:31:38.935539-04:00"
to represent date/time ([datetime]
) values, to compensate for the absence of a date/time data type in JSON itself - see this answer)Thus, you should use the following to create an object whose .myproperty
value contains an actual Boolean value - note that false
is unquoted:
$DataObject = ConvertFrom-Json @"
{
"myproperty": false
}
"@
Generally, aside from strings, which are always double-quoted (e.g., "foo"
), JSON supports the following unquoted primitive data types as values:
true
and false
null
42
, -42
, 1.0
and 1e2
+
or .1
as shorthand for 0.1
, and supports decimal number representations only; specific implementations, however, may be less strict.On the PowerShell / .NET side:
PowerShell's ConvertFrom-Json
maps these values to their analogous .NET data types, [string]
(System.String
) and [bool]
(System.Boolean
):
(' false ' | ConvertFrom-Json).GetType().FullName # -> System.Boolean
# vs.
(' "false" ' | ConvertFrom-Json).GetType().FullName # -> System.String
In terms of interpreting these values as Booleans, this means:
Only unquoted false
and true
values map directly onto their [bool]
counterparts (expressed as $false
and $true
in PowerShell).
As you've observed, when PowerShell evaluates a string in a Boolean context, it considers any non-empty string $true
, irrespective of its content, so that [bool] "false"
yields $true
as well.
"true"
or "false"
(or any case variation thereof) and you want to parse it as a Boolean, use the [bool]::Parse()
method; e.g., [bool]::Parse("false")
yields $false
, as intended.PowerShell generally implements its own, automatic to-Boolean conversions[1] (such as the one described above), which do not apply to .NET APIs.
DataContext
type to interpret strings as Booleans, though the use of [bool]::Parse()
is a logical candidate (in C# syntax, e.g.: bool.Parse("false")
)[1] For a summary of the conversion rules, see the bottom section of this answer.