JSONPath-Plus / JSONPath

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

match + regex combination is not working as expected for properties started or containing '@' #154

Open asatarov opened 3 years ago

asatarov commented 3 years ago

Describe the bug

if JSON key contains '@' symbol, match operation with regexp doesn't work as expected

Code sample or steps to reproduce

example json:

{
   "definitions": {
      "product": {
         "title": "product",
         "type": "object",
         "properties": {
            "@productId": {
               "type": "string"
            },
            "@baseProperty": {
               "type": "string"
            },
            "baseProperty@": {
               "type": "string"
            },
            "base@Property": {
               "type": "string"
            },
            "otherProperty": {
               "type": "string"
            },
            "anotherProperty": {
               "type": "string"
            }
         }
      }
   }
}

search results:

query result expected result
$.definitions.*.properties[?(@property.match(/\@/))]~ ["baseProperty@","base@Property"] ["@productId", "@baseProperty", "baseProperty@", "base@Property"]
$.definitions.*.properties[?(@property.match(/\x40/))]~ ["baseProperty@","base@Property"] ["@productId", "@baseProperty", "baseProperty@", "base@Property"]
$.definitions.*.properties[?(@property.match(/Property/))]~ ["baseProperty@","base@Property","otherProperty","anotherProperty"] ["baseProperty@","base@Property","otherProperty","anotherProperty", "@baseProperty"]
$.definitions.*.properties[?(@property.match(/o/))]~ ["baseProperty@","base@Property","otherProperty","anotherProperty"] ["baseProperty@","base@Property","otherProperty","anotherProperty", "@productId", "@baseProperty"]
$.definitions.*.properties[?(@property.match(/base/))]~ ["baseProperty@","base@Property"] ["baseProperty@","base@Property", "@baseProperty"]

Expected behavior

regex should work correctly with '@' symbols (e.g. as it works in https://regex101.com/)

Expected result

see table above

Environment (IMPORTANT)

https://extendsclass.com/jsonpath-tester.html

Desktop**

https://extendsclass.com/jsonpath-tester.html

brettz9 commented 3 years ago

Just a heads up that this repo is not very actively maintained. I have occasionally addressed some low-hanging fruit, but this one looks a little more involved, so afraid I cannot commit to investigating myself. PR would be welcome, however.

Note that our normal mechanism for escaping within a selector is to add ` before it. However, I see there is another problem in that even with just a @ property existing, I'm getting a maximum call stack size exceeded (at least adding a '@': 'something', property to the JSON in test.escaping.js).

Help on either problem would be most welcome.

Yobikap commented 2 years ago

This is very easy to fix maximum call stack size. The problem that you are getting is, you have a object that has circular references to another object in the same object. So to overcome this, I am doing the following:

yourfuntion(): void {
    const json = JSON.parse(this.jsonStringify(myJson));
    const result = JSONPath({path: 'yourpath', json: json})
}

  jsonStringify (obj: any): string {
    let cache: any[] | null = [];
    const retVal = JSON.stringify(
      obj,
      (key, value) =>
        typeof value === "object" && value !== null && cache !== null
          ? cache.includes(value)
            ? undefined // Duplicate reference found, discard key
            : cache.push(value) && value // Store value in our collection
          : value
    );
    cache = null;
    return retVal;
  }

Yes the original reference of the object is not updated.