JSONPath-Plus / JSONPath

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

Allow functions in the walk path of the query #186

Open machadofisher opened 1 year ago

machadofisher commented 1 year ago

Motivation

Dear all, regarding ORM frameworks and the lazy load topic, I tried to introduce the feature of using jsonpath queries to walk through lazy load data. To accomplish that objective we just need to allow functions names in path. The system should test if the type of var object in the walkpath is a function or not, if is a function, the function should be invoked. Functions with zero arguments, like gets should be enough. For example

User --> Cars but the cars property is not present, because ORM did not loaded it using eager policy users = [ { "name: "jonhDoe" "cars" : [] } ]

but if we are using for example, sequelize framework, the method getCars() should be there in order to query database.

so the jsonpath query should be: $.users[0].getCars.name

{ name: jonhDoe cars : [] getCars: function(){ //sequelize stuff added by the sequlelize ORM } }

The only problem of the async wait for the promises, where we have promises involved in middle

Current behavior

Currently the system do nothing when a function appears in the path, just print a warning I suppose

Desired behavior

System should invoke the function and go from there. In a first version the getters should be enough for most requirements.

Alternatives considered

Actually I have this working by changing the line ~ 370 of dist/index-node-cjs. by doing only this:

JSONPath.prototype._trace = function (expr, val, path, parent, parentPropName, callback, hasArrExpr, literalPriority) { // No expr to follow? return path and value as the result of // this trace branch ........ ....... if ((typeof loc !== 'string' || literalPriority) && val && hasOwnProp.call(val, loc)) {

  //------ OLD LINE:    addRet(this._trace(x, loc, push(path, loc), val, loc, callback, hasArrExpr));

  //NEW >>>>>>
  let varLoc = val[loc];
  if(typeof varLoc == "function")
  {
      varLoc = varLoc();
      //Check if it is a promise in order to await for it
      //await is not possible here because it is not an async function
  }
  addRet(this._trace(x, varLoc, push(path, loc), val, loc, callback, hasArrExpr));
  //NEW <<<<<

}

Many thanks