IBM / JSONata4Java

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

non-numeric value used as array index error when nested array predicate is first #205

Open schmurgon opened 2 years ago

schmurgon commented 2 years ago

Using the following as input

{
  "Email": [
    {
      "type": "work",
      "address": [{ "email":"fred.smith@my-work.com"}, {"email":"fsmith@my-work.com"}]
    },
    {
      "type": "home",
      "address": [{"email":"freddy@my-social.com"}, {"email":"frederic.smith@very-serious.com"}]
    }
  ]
}

I'm attempting to select and replace the element that matches the filter predicate:

(
    $emailElement := Email[    
       address[ email="fred.smith@my-work.com" ]
    ][0];

    $selectedEmailElements := {        
        "Email": [$emailElement]
    };

    $merge([$, $selectedEmailElements])
)

This works perfectly in the node version and on the demo https://try.jsonata.org/ but results in an exception on jsonata4java 1.7.9

com.api.jsonata4java.expressions.EvaluateException: non-numeric value used as array index at com.api.jsonata4java.expressions.Expressions.evaluate(Expressions.java:195) Caused by: com.api.jsonata4java.expressions.NonNumericArrayIndexException: non-numeric value used as array index at com.api.jsonata4java.expressions.ExpressionsVisitor.visitArray(ExpressionsVisitor.java:1018) at com.api.jsonata4java.expressions.ExpressionsVisitor.visitArray(ExpressionsVisitor.java:99) at com.api.jsonata4java.expressions.generated.MappingExpressionParser$ArrayContext.accept(MappingExpressionParser.java:521)

When the expression is changed to include a meaningless predicate prior to the array filter then the correct result is returned as expected:

(
    $emailElement := Email[    
      "1" = "1" and /* HACK */
       address[ email="fred.smith@my-work.com" ]
    ][0];

    $selectedEmailElements := {        
        "Email": [$emailElement]
    };

    $merge([$, $selectedEmailElements])
)

Result

{
  "Email" : [ {
    "type" : "work",
    "address" : [ { "email" : "fred.smith@my-work.com" }, { "email" : "fsmith@my-work.com" } ]
  } ]
}
wnm3 commented 2 years ago

Hi Ben, we had elected to defer supporting the non-numeric indices as the original use cases envisioned would not have included them. This will take some work. You can look at the ExpressionVisitor.json visitArray method starting on line 885 and see where the exception is being thrown (1018). Quite a bit of additional logic is required to support the filtering you seek.