Different behaviour than on jsonLogic.com for some operators
Hi, my team and I recently discovered that the "+" and "*" operators don't work exactly as documented on the jsonLogic site. It appears like your implementation avoids having null values when working with these operators and tries to return a non-null value while the jsonLogic site returns null.
i.e. for 0 + null, jsonLogic site returns null while this library returns 0.
However, we have a use case to return null when evaluating the logic and have thus implemented the following operators:
operators.DeleteOperator("+");
operators.AddOperator("+", (p, args, data) => Min2From(args.Select(a => p.Apply(a, data))).Aggregate((prev, next) =>
{
try { return prev != null ? (double?)(Convert.ToDouble(prev) + Convert.ToDouble(next)) : null; }
catch { return prev.ToString() + next.ToString(); }
}));
operators.DeleteOperator("*");
operators.AddOperator("*", ReduceDoubleArgs(null, (prev, next) => (next == null) ? null : prev * next));
Perhaps this support for returning null values can be added as part of some settings, should you see fit.
@kph21, Thanks for providing code sample for the expected behavior. I will review the differences. Meanwhile, if you do a pull request with the tests and the fix, we might get it patched up in nuget faster. :)
Hello, I might have run into something similar.
The following rule results in a NullReferenceException. {">=": [null, 60]}"
The javascript version seems to treats null as 0. For compatibility reasons I have this workaround. Not sure if this is the correct way of solving it or if there are more edge cases. Perhaps something to consider adding to the library.
operators.AddOperator(">=", DoubleArgsSatisfy2((a, b) => a >= b));
operators.AddOperator("<=", DoubleArgsSatisfy2((a, b) => a <= b));
...
public static bool IsNull(this JToken token)
{
return (token == null) ||
(token.Type == JTokenType.Object && !token.HasValues) ||
(token.Type == JTokenType.Null);
}
private static Func<IProcessJsonLogic, JToken[], object, object> DoubleArgsSatisfy2(Func<double, double, bool> criteria)
{
return (p, args, data) => {
var values = args.Select(a => ((a == null) || a.IsNull()) ? 0d : Double.Parse(p.Apply(a, data).ToString())).ToArray();
for (int i = 1; i < values.Length; i++) {
if (!criteria(values[i-1], values[i])) return false;
}
return true;
};
}
Thanks