react-querybuilder/react-querybuilder

JSONata Parser/Importer

Closed this issue · 6 comments

Description of the feature

With the recent request for exporting to JSONata (#677), it would beneficial to be able to import the JSONata code back into RQB.

Use case

Having previously used the changes from #684 to use RQB to build a JSONata condition, a user should be able to edit the expression in RQB in the future. This requires RQB to be able to import/parse the JSONata expression.

In implementing this I found it easiest to maintain the native types when dealing with values that aren't strings, and I wanted to get your feedback. For example, the JSONata condition age = 26 would translate to { field: 'age', operator: '=', value: 26 }, where the value is type number.

This gets a little trickier with non-primitive values like RexExp. It's easy enough to set value: /whatever/ig, but the default ValueEditor component has no way to deal with regexes so you as a developer would need to implement a custom value editor (or at least a wrapper, as shown here).

Another option would be to stringify everything. This would have the benefit of keeping the query object serializable. Values of type RegExp would be translated to strings using the .source property, and the developer could build a proper regex from that string if they wanted. The downside of that is it would lose the modifiers like i and g. Numbers would easily translate back and forth to strings, but arrays might get messy. Objects would just be JSON.stringify'd and would probably need a custom handler as well.

We could also make it configurable with a stringifyValues option or something like that. I think my preference would be to simply leave the values in their native format with no config option, but let me know if that's not acceptable.

@jakeboone02
I think I prefer the custom value editor option.

When I was testing, I already implemented the Custom components with fallbacks logic, so that method seems pretty easy for me.
(I wanted to handle deep object property selection since my case use will deal with setting workflow starting conditions from a complex JSON object)

I also would just rather write a custom component than deal with extra serialization/deserializion.

But I'm okay with either and will defer to what you think fits the culture of the project more!

I implemented parseJSONata in #688. You can try it using the "Import JSONata" button (bottom left-hand side) in the preview website demo.

Notes:

  • This currently only handles expressions with known conditional operations. The "selection" parts of JSONata are ignored. For example, 'age = 26' will be parsed, but '*[age = 26]' will not. I'd like to get your thoughts on how we can drill down into the AST to get to the conditions and build the query appropriately. Some example JSONata expressions, along with the subject data, would probably be helpful.
  • The parser retains value types as we discussed, so strings, numbers, booleans, and RegExp's will stay what they are. The only exception I made to that rule was with the $toMillis function. When that function is used on the value side of a comparison, the first argument (the date string) will be used as the rule's value. The second argument, the format string, will be ignored. For example, the JSONata condition 'birthDate = $toMillis("1954-10-03", "invalid-format")' translates to the RQB rule { field: "birthDate", operator: "=", value: "1954-10-03" }.
  • I couldn't quickly come up with a way to detect "beginsWith" and "endsWith" operators, since that would mean parsing the actual regex passed to the $contains function. I could probably do it eventually, but for now all conditions using the $contains function translate to operator: "contains".

Let me know what you think!

Hey @jnallard - just checking in to see if you've had time to look at my last #685 (comment).

Hi @jakeboone02,

I'm sorry for my late reply!
My team was pulled onto another project and we had to pause the project that we wanted to use react-querybuilder for, but what I see looks great!

For the selection parts of JSONata, I'm perfectly happy with what you've done so far. For our use case, we had intended to only handle simple cases with the query builder (with maybe a free-form text editor for more advanced usage)

Thanks for all the help on this!

Great! Thanks for looking into it. I'll go ahead and merge the PR. Once I release it I'll add a note that it's "experimental" or something like that.