IBM / JSONata4Java

Open Source Java version of JSONata
Apache License 2.0
91 stars 38 forks source link

The $round function returns an empty string when passed a null object #308

Open brainesy opened 4 months ago

brainesy commented 4 months ago

When passing a null object to the round function, the returned value is an empty string. A null return value would have been expected (as provided by the javascript implementation of this function). By returning a string, subsequent expressions that may check for zero values, or the existence of a value can fail.

Example using jsonata4java version 2.4.9

$data := {
    "a": 1,
    "b": 2
};

$result := $round( $data.xyz, 0);

Expected result: null (i.e: no result) Actual result: "" Result using Javascript version 2.0.5: null / undefined / no match

wnm3 commented 4 months ago

Hi, testing v2.4.9 with the following returns null (no match in Tester): ($data := { "a":1, "b":2 } ; $result = $round($data.xyz,0) ; $result) and below returns "is null": ($data := { "a":1, "b":2 } ; $result = $round($data.xyz,0) ; $result=null ? "is null":"not null")

You could change RoundFunction.java line 94: if (argNumber == null || argNumber instanceof NullNode) {

However, this breaks the unit tests and would deviate from the jsonata.org implementation as $round(null,0) should complain about the 1st argument as evidenced in this test: https://try.jsonata.org/X4VtoczxS

I'd prefer not to deviate if possible.

brainesy commented 4 months ago

Thanks for the response. Looking into this further, it appears that the empty string only results when storing the result of the round function into a variable:

Example:

$data := {
    "a": 1,
    "b": 2
};

$roundVariable := $round( $data.xyz, 0);

{
    "roundVariable": $roundVariable,
    "existsVariable": $exists($roundVariable),
    "expression": $round( $data.xyz, 0),
    "existsExpression": $exists($round( $data.xyz, 0))
};

The result is:

{
  "roundVariable" : "",
  "existsVariable" : true,
  "existsExpression" : false
}

In the above output, the variable $roundVariable contains an empty string causing the $exists function to return true. However, when using the expression directly, a null value is returned, causing $exists to return false.

wnm3 commented 4 months ago

This seems like a tip of an iceberg... I can patch to return a NullNode but the exists function still shows true since the variable is pointing at a function. And, there are tests from jsonata.org for the function-string.case027, 018, and 028 that expect the empty string when a variable points to a function. I'll revisit in a bit to see if I can determine why it is an empty string sometimes and a NullNode in others.