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 ?
CodePudding user response:
On the JSON side:
false
andtrue
- 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 befalse
andtrue
, respectively - a string value has no intrinsic meaning, except by convention that the consumer of a JSON document must be aware of.- (An example of such a convention is that
ConvertTo-Json
andConvertFrom-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)
- (An example of such a convention is that
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:
- Booleans:
true
andfalse
- Null values:
null
- Numbers: e.g.,
42
,-42
,1.0
and1e2
- Note: The standard doesn't permit prefix
.1
as shorthand for0.1
, and supports decimal number representations only; specific implementations, however, may be less strict.
- Note: The standard doesn't permit prefix
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
andtrue
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.- If you're dealing with string that you know to contain either
"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.
- If you're dealing with string that you know to contain either
PowerShell generally implements its own, automatic to-Boolean conversions[1] (such as the one described above), which do not apply to .NET APIs.
- Given that .NET has no built-in string-to-Boolean conversion, it is up to the
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")
)
- Given that .NET has no built-in string-to-Boolean conversion, it is up to the
[1] For a summary of the conversion rules, see the bottom section of this answer.