在子对象中计算JSON表达式

shyt4zoc  于 2023-01-14  发布在  其他
关注(0)|答案(2)|浏览(129)

我尝试使用Josson计算json表达式,但它给出了无效函数错误

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)"));

堆栈跟踪:

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)
rjee0c15

rjee0c151#

数学公式中的变量不能包含特殊字符。你需要使用替换。变量名可以是任何你想要的,没有特殊字符和.。所以,B的语句变成...

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

查询data.eval(B)中的函数eval()作用于节点data,所以原来的求值语句需要$.从根节点重新开始取值,对于这个修改版本eval(data.B)eval()作用于根节点,参数为data.B,所以$.是不需要的。

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\": 200\n" +
    "    },\n" +
    "    \"ModelMaster\": {\n" +
    "        \"count\": 20\n" +
    "    }\n" +
    "}";
Josson josson = Josson.fromJsonString(json);
System.out.println(josson.getNode("eval(data.B)"));
// Output: 19548.0
b1uwtaje

b1uwtaje2#

Answer by Raymond Choi将是最佳解决方案。
好吧,我已经找到了一个可能的解决方案,这使用乔森模板引擎。

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)"));

有必要调整JSON字符串以使用占位符来访问不同/嵌套节点的值。我们还必须使用已填充的模板创建新的JSON字符串。此外,遗憾的是,它不会递归地替换占位符。使得必须调用jossons.fillInPlaceholder()两次。第一次获取计算公式,第二次替换公式中现有的占位符。
输出为:

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

问题中建议的代码失败了,因为Josson无法解析嵌套/不同的节点值。几乎只要.出现在calc()公式中,语法检查就会失败。但是,可以访问同一级别的节点。因此,如下所示的JSON:

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

可通过以下方式进行评价:

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)"));

结果相同:19548.0.
无论哪种方式,都必须调整输入JSON以使用Josson

相关问题