JSONPath-Plus / JSONPath

A fork of JSONPath from http://goessner.net/articles/JsonPath/
Other
963 stars 169 forks source link

condition on the root #118

Closed gsouf closed 4 years ago

gsouf commented 4 years ago

Hi,

I have this kind of json:

{
   foo: 'bar',
   baz: 'qux'
}

I want to read value of baz only if foo === "bar". I can get it to work for array structures, but not at the root.

I tried many things like:

$[?(@.foo === "bar")].baz
$?(@.foo === "bar").baz
$.baz[?(@parent.foo === "bar")]
etc..

It just looks like we cannot operate any filters on the root element.

brettz9 commented 4 years ago

Yes, I believe you're right that there is no current core way to achieve this pretty fundamental filtering type (by object)--not only at root but anywhere. I think there may not have been a great need previously since programmers would tend to drill down before or afterward.

The only option you could have--if the engine is under your control (though if it were, I presume you could also add the root inside an array)--would be to use otherTypeCallback:

const {JSONPath} = require("jsonpath-plus")

const json = {
   foo: 'bar',
   baz: 'qux'
};

JSONPath({path: '$.@other()', json, otherTypeCallback (value, path, parent, parentPropertyName) {
  return value && value.foo === 'bar';
}});

Demo: https://runkit.com/brettz9/5e8c8b95dee34d001c58e0f2

gsouf commented 4 years ago

@brettz9 thanks for your answer! Actually I didn't give up and I tried again. And I found a way to achieve it. Not the most easy to understand when reading but at least it works:

  $[?(@property === "foo" && @ === "bar")]^.baz

We filter the property by name and value in order to get 0 or 1 (and only 1) match if the property matches. Then when go back to the parent (because we ensured to have 0 or 1 match then it will return the parent only if the propety matched). Then we just do the stuff on the parent.

I'm closing this one because it's solved for me.

brettz9 commented 4 years ago

Ahhh--shows how much I know! :) Nice work finding the way!

I just now added a note on the README to highlight this possibility, so it is now hopefully more evident what is possible (though if not, I'm open to doc PRs).