Parsing and evaluating complex objects using JInt

709 Views Asked by At

I have a requirement to evaluate certain expressions, and based on the evaluation choose the next steps. I am trying to use JInt javscript interpreter for this.

For basic evaluations from json, it is working fine. But when I am trying to add additional operations on array, that's where the issue is coming.

My approach, set value for base objects => write a function to evaluate expressions => invoke this function and pass the expression to evaluate => function will use eval to evaluate passed string. Initial objects are already set in previous steps.

Something like this,

inputStart.Reference.CompanyCode == \"ABC\"

In this, inputStart is the base object which I have already set using

engine.SetValue("inputStart", JsonConvert.DeserializeObject(inputStart));

inputStart is json text. Fiddle has the string as well for reference. And finally the function,

engine.Execute("function evaluateExpression(expression) { " +
                       "return eval(expression); " +
                       "}")
            .GetValue("evaluateExpression");

var test = engine.Invoke("evaluateExpression", "inputStart.Reference.CompanyCode == \"ABC\"");

This code works correctly. Now the variation is, I have another json text which has array in it. And I am trying to use filter or find to locate specific array item, and then have some operation on it. Something like this,

inputQuestions.Questions.filter((x) => x.Code == \"INIT_IMP\")[0].Answer.Answer.Code

This gives me below error,

Unhandled exception. System.ArgumentException: Accessed JArray values with invalid key value: "filter". Int32 array index expected.

My complete program for reference,

string inputStart = "{\n\t\"PurposeCode\": \"START\",\n\t\"Reference\": {\n\t\t\"CompanyCode\": \"ABC\"\t\t\n\t}\n}";
string inputQuestions = "{\n\t\"QuestionSetCode\": \"QUES_SET_1\",\n\t\"Version\": 1,\n\t\"Questions\": [{\n\t\t\"Code\": \"INIT_IMP\",\n\t\t\"Text\": \"Impact ?\",\n\t\t\"AnswerType\": 3,\n\t\t\"SequenceNumber\": 1,\n\t\t\"Answer\": {\n\t\t\t\"Answers\": [{\n\t\t\t\t\"Code\": \"INIT_IMP_DO\",\n\t\t\t\t\"Text\": \"A\",\n\t\t\t\t\"SequenceNumber\": 1\n\t\t\t}, {\n\t\t\t\t\"Code\": \"INIT_IMP_DA\",\n\t\t\t\t\"Text\": \"B\",\n\t\t\t\t\"SequenceNumber\": 2\n\t\t\t}, {\n\t\t\t\t\"Code\": \"INIT_IMP_AO\",\n\t\t\t\t\"Text\": \"C\",\n\t\t\t\t\"SequenceNumber\": 3\n\t\t\t}],\n\t\t\t\"Answer\": {\n\t\t\t\t\"Code\": \"INIT_IMP_DO\",\n\t\t\t\t\"Text\": \"A\",\n\t\t\t\t\"SequenceNumber\": 1\n\t\t\t},\n\t\t\t\"Type\": \"ListOfValuesAnswer\"\n\t\t},\n\t\t\"Applicable\": true\n\t}, {\n\t\t\"Code\": \"ENT_ACC_LIQ\",\n\t\t\"Text\": \"Exposure ?\",\n\t\t\"AnswerType\": 3,\n\t\t\"SequenceNumber\": 2,\n\t\t\"Answer\": {\n\t\t\t\"Answers\": [{\n\t\t\t\t\"Code\": \"ENT_ACC_LIQ_Y\",\n\t\t\t\t\"Text\": \"Yes\",\n\t\t\t\t\"SequenceNumber\": 1\n\t\t\t}, {\n\t\t\t\t\"Code\": \"ENT_ACC_LIQ_N\",\n\t\t\t\t\"Text\": \"No\",\n\t\t\t\t\"SequenceNumber\": 2\n\t\t\t}],\n\t\t\t\"Answer\": {\n\t\t\t\t\"Code\": \"ENT_ACC_LIQ_N\",\n\t\t\t\t\"Text\": \"No\",\n\t\t\t\t\"SequenceNumber\": 2\n\t\t\t},\n\t\t\t\"Type\": \"ListOfValuesAnswer\"\n\t\t},\n\t\t\"Applicable\": true\n\t}],\n\t\"ClientId\": null\n}";
        
Engine engine = new Engine();
        
engine.SetValue("inputStart", JsonConvert.DeserializeObject(inputStart));
engine.SetValue("inputQuestions", JsonConvert.DeserializeObject(inputQuestions));
        
engine.Execute("function evaluateExpression(expression) { " +
                       "return eval(expression); " +
                       "}")
            .GetValue("evaluateExpression");

var test = engine.Invoke("evaluateExpression", "inputQuestions.Questions.filter((x) => x.Code == \"INIT_IMP\")[0].Answer.Answer.Code == \"INIT_IMP_DO\" && inputStart.Reference.CompanyCode == \"ABC\"");
        
Console.WriteLine(test);

Here is the complete fiddle for what I am trying to do, https://dotnetfiddle.net/GtamM8

If anyone has come across such issue, or can suggest a solution to this, it will be very helpful.

1

There are 1 best solutions below

0
Marko Lahma On

Because you are using the new language constructs, you should be using 3.x preview release from NuGet. 3.x series contains support for lambda expressions and array filtering against them.