skip to Main Content

I am trying to evaluate json expression using Josson, but it gives invalid function error

String json ="{"data":{"B":"calc(348+(96*$.SelectedPump.stg*$.ModelMaster.count))"},"SelectedPump":{"stg":10,"ab":200},"ModelMaster":{"count":20}}";
        
Josson josson = Josson.fromJsonString(json.toString());
System.out.println(josson.getNode("data.eval(B)"));

Stacktrace:

Exception in thread "main" java.lang.IllegalArgumentException: Invalid function call eval() : Invalid function call calc() : Calc syntax error.
    at com.octomix.josson.FuncDispatcher.apply(FuncDispatcher.java:84)
    at com.octomix.josson.JossonCore.getPathBySteps(JossonCore.java:328)
    at com.octomix.josson.JossonCore.getPathBySteps(JossonCore.java:352)
    at com.octomix.josson.JossonCore.getPathBySteps(JossonCore.java:249)
    at com.octomix.josson.JossonCore.getPathByExpression(JossonCore.java:211)
    at com.octomix.josson.JossonCore.getNodeByExpression(JossonCore.java:147)
    at com.octomix.josson.JossonCore.getNodeByExpression(JossonCore.java:142)
    at com.octomix.josson.Josson.getNode(Josson.java:279)

2

Answers


  1. Answer by Raymond Choi would be the best solution.


    Alright, I have found a possible solution to this using Jossons template engine.

    String json = "{"data":{"B":"calc(348+(96*{{SelectedPump->stg}}*{{ModelMaster->count}}))"},"SelectedPump":{"stg":10,"ab":200},"ModelMaster":{"count":20}}";
    
    Jossons jossons = Jossons.fromJsonString(json);
    String output = jossons.fillInPlaceholder("{"s":"{{data->B}}"}");
    output = jossons.fillInPlaceholder(output);
    System.out.println(output);
    System.out.println(Josson.fromJsonString(output).getNode("$.eval(s)"));
    

    It is necessary to adjust the JSON string to use placeholder to access the values from a different/nested node. We also have to create a new JSON string with a template that is filled in. Also also, it does sadly not recursively replace the placeholder, making it necessary to call jossons.fillInPlaceholder() two times. The first time it fetches the calculated formula and the second time it replaces the placeholder that are now present in the formula.

    The output is:

    output -> {"s":"calc(348+(96*10*20))"}
    Josson.fromJsonString(output).getNode("$.eval(s)") -> 19548.0
    

    The proposed code in the question fails, because Josson is not able to resolve nested/different node values. Pretty much as soon as we have a . present in the calc() formula, the syntax check fails. It is however possible to access nodes at the same level. So a JSON like this:

    {
      "data" : {
        "B" : "calc(348+(96*SelectedPumpStg*ModelMasterCount))",
        "SelectedPumpStg" : 10,
        "ModelMasterCount" : 20
      }
    }
    

    can be evaluated by:

    String json = "{"data":{"B":"calc(348+(96*SelectedPumpStg*ModelMasterCount))","SelectedPumpStg":10,"ModelMasterCount":20}}";
    Josson josson = Josson.fromJsonString(json.toString());
    System.out.println(josson.getNode("data.eval(B)"));
    

    resulting in the same: 19548.0.

    Either way, the input JSON has to be adjusted to work with Josson

    Login or Signup to reply.
  2. The variables inside the math equation cannot contains special characters. You need to use substitution. The variable name can whatever you want without special characters and .. So, the statement of B become…

    calc(348+(96*A*B), A:SelectedPump.stg, B:ModelMaster.count)
    

    The function eval() in query data.eval(B) works on node data. So the original evaluation statement needs $. to re-start from the root to get the value. For this revised version eval(data.B), eval() works on the root node with parameter data.B. And therefore, $. is not necessary.

    String json =
        "{n" +
        "    "data": {n" +
        "        "B": "calc(348+(96*A*B), A:SelectedPump.stg, B:ModelMaster.count)"n" +
        "    },n" +
        "    "SelectedPump": {n" +
        "        "stg": 10,n" +
        "        "ab": 200n" +
        "    },n" +
        "    "ModelMaster": {n" +
        "        "count": 20n" +
        "    }n" +
        "}";
    Josson josson = Josson.fromJsonString(json);
    System.out.println(josson.getNode("eval(data.B)"));
    // Output: 19548.0
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search