Why can't I compare JSON variable with [PlantUML] boolean?

0 votes
asked Nov 9, 2021 in Question / help by The-Lu (64,340 points)

Hello PlantUML team,

From:

- Why can't I compare JSON variable with boolean?
or How to store PlantUML boolean on JSON variable?

I got very confused with the test of boolean value from JSON variable.

Here is an example:

@startuml
!$json = {
"value": ["0", 0 , false, null, true, "1", 1, ""]
} 
:$json.value;

split
:test of 'v';
!foreach $v in $json.value
!if ( $v )
#palegreen:is true;
!else
#pink:is false;
!endif
!endfor
kill

split again
:test of 'v == <U+0025>true()';
!foreach $v in $json.value
!if ( $v == %true() )
#palegreen:is true;
!else
#pink:is false;
!endif
!endfor
kill
endsplit
@enduml

If that is clear, wink
Regards,
Th.

commented Nov 9, 2021 by Martin (8,360 points)
edited Nov 9, 2021 by Martin

I think there are a few different considerations here.

1) ($V) and ($V == %true()) are not the same thing. 
As per the documentation:

  • Integer 0 means false
  • and any non-null number (as 1) or any string (as "1", or even "0") means true.

So although %true() evaluates to 1, it doesn't mean that something that is true must equal 1.

Your test would be better (but not perfect) as ($V != %false())

2) As per the above, the string "0" is true, since only the value 0 is false.  I suspect that JSON is returning strings for every value even the numeric ones - so everything out of JSON (except an empty string) is true.  If you replace "!if ($v)" with "!if (%intval($v))" then you get closer to your boolean test.
For interest, check out this:

@startuml
!$json = { "value": ["0", 0 , "1", 1, "10", 10] } 
!foreach $v in $json.value
  :%eval($v+1);
!endfor
@enduml

3) Plantuml is doing something clever with if (string==int).  You'll find that ("1"==1)  is true, so is ("0"=0).  In particular: although "0" is true, "0" does equal %false() !

@startuml
!$v="0"
!if ($v && $v==%false()) 
:"0" is special;
!else
:"0" is normal;
!endif
@enduml

4) The JSON foreach does do something special with true/false/null but I can't work out what.
If you define:

!$json = { "value": [true] } 

then you can quite happily use:

:$json.value[0];

And it displays "true".  But if instead you use:

!foreach $v in $json.value
  :$v;
!endfor

then you get a fatal parsing error.  But:

!foreach $v in $json.value
  :%substr($v,0);
!endfor

works fine...  I'm not sure what to make of that...maybe that JSON is storing [true] differently to ["true"] and foreach can access the raw internal value, but as soon as it is used in a string context (eg an IF statement) then it auto-converts to a string.

commented Nov 9, 2021 by The-Lu (64,340 points)

Hello all,

Thank you @Martin for all the explanations and complete and in-depth examples.

I had not seen all these subtleties (while writing the doc.): So here there now are gathered together.

All that remains is to correct the doc., and maybe some corrections on plantuml ... (to the PlantUML team to see)... wink

- This is where we see the complexity of a language ... (and of the construction of a language) ... -

Regards.

Your answer

Your name to display (optional):
Privacy: Your email address will only be used for sending these notifications.
Anti-spam verification:

[Antispam2 Feature: please please wait 1 or 2 minutes (this message will disappear) before pressing the button otherwise it will fail](--------)
To avoid this verification in future, please log in or register.
...