js-to-json-logic icon indicating copy to clipboard operation
js-to-json-logic copied to clipboard

Allow to flatten same logical operations

Open Ketler13 opened this issue 4 years ago • 5 comments

The problem Consider having such flat logical expression as a string: first === 1 || second === 2 || third === 3 After transformation to the json logic it will be changed to the tree: {"or":[{"or":[{"===":[{"var":"first"},1]},{"===":[{"var":"second"},2]}]},{"===":[{"var":"third"},3]}]} So instead of flat structure it will be nested. Then, if I try to use that structure with https://github.com/ukrbublik/react-awesome-query-builder the result UI will be like this: image

Possible solution This PR tries to flatten only logical expression node if it's left or right children are also logical expression with the same operator. Please take a look at the results after applying changes: {"or":[{"===":[{"var":"first"},1]},{"===":[{"var":"second"},2]},{"===":[{"var":"third"},3]}]} image

Notes This is just an idea and maybe it is completely wrong for complex cases. Also maybe it's ok to have it in options to be able to allow/disable flattening from outside code. Thank you for the library, it is very useful.

Ketler13 avatar Nov 05 '20 08:11 Ketler13

This is a good callout, I was surprised that the given example in the readme, which is transformJS('temp < 110 && pie.filling === "apple"') works as expected but add another && block transformJS('temp < 110 && pie.filling === "apple" && iceCream === true') and now it's nested:

{
  and: [
    {
      and: [
        { '<': [ { var: 'temp' }, 110 ] },
        { '===': [ { var: 'pie.filling' }, 'apple' ] }
      ]
    },
    { '===': [ { var: 'iceCream' }, true ] }
  ]
}

Maybe there's something I'm not understanding.

juniorclearmetal avatar Jan 27 '21 20:01 juniorclearmetal

@juniorclearmetal I believe this happens not in this library itself, but rather in underlying JS parser (I guess this is meriyah package in this case). For this expression 'temp < 110 && pie.filling === "apple" && iceCream === true' parser will generate binary tree and there will always be left-hand and right-hand expression. Something like this: { op: '&&', left: temp < 110, right: pie.filling === "apple" && iceCream === true' } and then right part will consist of: { op: '&&', left: pie.filling === "apple", right: iceCream === true' } So in terms of binary tree result this expression looks correct. These are just initial thoughts, maybe it will be useful to take a look for example how prettier simplifies such kind of nested boolean expressions.

Thank you

Ketler13 avatar Feb 01 '21 12:02 Ketler13

Goodness this PR was lost in my notifications and I never noticed @Ketler13 I'll review and merge this soon. Sorry for the huge delay

krismuniz avatar Mar 20 '21 17:03 krismuniz

@krismuniz Can we expect a merge on this, or is there any problem with it?

I tried out this library and as it turns out, if you want to save a really long expression without the flattening, the mysql json column fails. My workaround is, that we use more parenthesis.

gazben avatar Jul 23 '21 15:07 gazben

Yeah, is this PR still on the table?

Marcisbee avatar Apr 22 '22 09:04 Marcisbee