SchmitzIT
SchmitzIT

Reputation: 9552

JSONPath regular expression - NOT starting with

My JSON (simplified) looks like this:

[
    {"name" : "foobar",
      "id" : 123
    },
    {"name" : "bar",
      "id" : 123
    },
    {"name" : "foobar",
      "id" : 456
    }, ...
]

I'm using https://jsonpath.herokuapp.com/ to try and find the right JSONPATH syntax to filter out anything not starting with foo, and having id == 123.

Getting it to filter the ones that do start with foo is easy:

$..[?(@.name =~ /foo.*/i)]

This yields the following results:

[
   {
      "name" : "foobar",
      "id" : 123
   },
   {
      "name" : "foobar",
      "id" : 456
   }
]

I can get rid of the id 456 by adding an additional filter like so:

$..[?(@.name =~ /foo.*/i && @.id==123)]

But how do I do the opposite of getting the name starting with foo? I want all entities that do not start with foo.

I tried something like this:

$..[?([email protected] =~ /foo.*/i && @.id==123)]

Which at least parses as valid JSONPATH, and should negate the filter, but for some reason it still happily only reports the foobar entry:

[
   {
      "name" : "foobar",
      "id" : 123
   }
]

How can I achieve a NOT LIKE in JSONPATH?

Thanks!

Upvotes: 0

Views: 5698

Answers (3)

riyasvaliya
riyasvaliya

Reputation: 825

Your attempt $..[?([email protected] =~ /foo.*/i && @.id==123)] is almost correct. Surround the regex condition with parenthesis before negating with ! like so $..[?(!(@.name =~ /foo.*/i) && @.id==123)]. Tested at https://jsonpath.herokuapp.com/

Edit: This was assuming that you were using Jayway's jsonpath (Java, https://github.com/json-path/JsonPath), but from the documentation link you provided for SmartBear, it looks like it uses the Goessner jsonpath (Javascript, https://goessner.net/articles/JsonPath/). Both, for whatever reason use slightly differing syntaxes.

Upvotes: 1

SchmitzIT
SchmitzIT

Reputation: 9552

Thanks to @collapsar for nudging me in the correct direction, in that the key to solving it was in the regular expression (but specifically using the JavaScript Regular Expression syntax, and merging that with the JSONPath syntax).

What actually ended up doing the trick was reading the documentation for JASONPath a bit more careful. It states:

=~
Match a JavaScript regular expression. For example, [?(@.description =~ /cat.*/i)] matches items whose description starts with cat (case-insensitive).

Note: Not supported at locations that use Ready! API 1.1.

The link to Javascript Regular Expression in turn contains the following:

[^xyz]
A negated or complemented character set. That is, it matches anything that is not enclosed in the brackets. You can specify a range of characters by using a hyphen. Everything that works in the normal character set also works here.

For example, [^abc] is the same as [^a-c]. They initially match 'r' in "brisket" and 'h' in "chop."

The resulting expression that works is:

$..[?(@.name =~ /[^foo].*/ && @.id == 123)]

Result:

[
   {
      "name" : "bar",
      "id" : 123
   }
]

(I added an additional bar with id 456 to the JSON payload I had, to double-check the filter also worked).

Upvotes: 0

collapsar
collapsar

Reputation: 17238

Regex to identify data not starting with a given string foo:

^([^f]|f[^o]|fo[^o])

If your regex engine supports negative lookahead, that reduces to

^(?!foo)

Note the starting anchor (^) that limits the permissible matching location to the start of the test string.

Upvotes: 1

Related Questions