2

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 ?

1 Answer 1

4

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.

    • (An example of such a convention is that 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:

  • Booleans: true and false
  • Null values: null
  • Numbers: e.g., 42, -42, 1.0 and 1e2
    • Note: The standard doesn't permit prefix + 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.

    • 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.
  • 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"))

[1] For a summary of the conversion rules, see the bottom section of this answer.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.