Coder Social home page Coder Social logo

nimma's People

Contributors

frederickayser avatar p0lip avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

nimma's Issues

JSON Path is getting an IETF spec!

It looks like the spec draft that you've based your implementation on is old. Check out the details at https://github.com/ietf-wg-jsonpath/draft-ietf-jsonpath-base. There have been quite a few changes (with good reason) since you last looked.

Mainly:

  • in and =~ are no longer valid operators.
  • functions in expressions

Also, I would recommend hiding JsonPath-Plus features behind a default-off configuration option to align with the spec.

There's also a comparison website which lists a bunch of paths and various implementations' results. I've added an issue to add this lib. I'll be working on it (I am not a JS dev), but if you want to add it yourself, feel free. It'd be great to have another implementation there.

And if you want to join in the coversation for developing the spec, you'd be welcome!

JSONPath-plus support

Hi Jakub!

In the README there is a statement:

Supports the majority of JSONPath-plus additions

Is there a list of supported features?

I've tried to use things like @root, @parent — it doesn't work for me... does Nimma support them?

Unexpected multiple traversals

So in the readme it states:

[...] whereas Nimma, for the most time, doesn't really care whether you supply it with 10s or 100s of paths. [...]

Unfortunately multiple paths mean multiple accesses when using Nimma. This is a huge deal when many input paths are given or slow getters are used.

This should definitely be mentioned in the Readme. It is probably the biggest and most fundamental difference to object-scan.

Click to show Test Case
import Nimma from 'nimma';
import objectScan from 'object-scan';

class AccessLogger {
  constructor(obj) {
    const logs = {};
    const prepare = (o) => {
      const entries = Object.entries(o);
      const result = {};
      for (let i = 0; i < entries.length; i += 1) {
        const [k, v] = entries[i];
        const value = prepare(v);
        result[k] = value;
        Object.defineProperty(result, k, {
          get() {
            if (!(k in logs)) {
              logs[k] = 0;
            }
            logs[k] += 1;
            return value;
          }
        });
      }
      return result;
    };
    this.logs = logs;
    this.obj = prepare(obj);
  }

  reset() {
    const logs = { ...this.logs };
    Object.keys(this.logs).forEach((k) => {
      delete this.logs[k];
    });
    return logs;
  }
}

const accessLogger = new AccessLogger({
  a: {
    b: {
      c: {},
      d: {},
      e: {}
    }
  }
});
const { obj } = accessLogger;

const keysNimma = [
  '$.a.b.c',
  '$..*',
  '$.a.b.d',
  '$.a.b.e',
  '$.a.*.e',
  '$..e',
  '$.*.*',
  '$..b.c',
  '$.a.b'
];
const keysObjectScan = keysNimma
  .map((k) => (k.startsWith('$..') ? `**${k.slice(2)}` : k.slice(2)))

const testNimma = () => {
  const callbacks = [];
  new Nimma(keysNimma).query(obj, keysNimma.reduce((p, k) => ({
    ...p,
    [k]({ value, path }) {
      callbacks.push([path.join('.'), k, value]);
    }
  }), {}));
  return { callbacks, access: accessLogger.reset() };
};

const testObjectScan = () => {
  const callbacks = objectScan(keysObjectScan, {
    joined: true,
    filterFn: ({ matchedBy, key, value, context }) => {
      matchedBy.forEach((m) => {
        context.push([key, m, value]);
      });
    }
  })(obj, []);
  return { callbacks, access: accessLogger.reset() };
};

console.log(testNimma());
/*
{
  callbacks: [
    [ 'a.b.c', '$.a.b.c', {} ],
    [ 'a.b.d', '$.a.b.d', {} ],
    [ 'a.b.e', '$.a.b.e', {} ],
    [ 'a.b', '$.a.b', [Object] ],
    [ 'a', '$..*', [Object] ],
    [ 'a.b', '$..*', [Object] ],
    [ 'a.b', '$.*.*', [Object] ],
    [ 'a.b.c', '$..*', {} ],
    [ 'a.b.c', '$..b.c', {} ],
    [ 'a.b.d', '$..*', {} ],
    [ 'a.b.e', '$..*', {} ],
    [ 'a.b.e', '$.a.*.e', {} ],
    [ 'a.b.e', '$..e', {} ]
  ],
  access: { a: 10, b: 9, c: 3, d: 3, e: 3 }
}
*/
console.log(testObjectScan());
/*
{
  callbacks: [
    [ 'a.b.e', 'a.b.e', {} ],
    [ 'a.b.e', 'a.*.e', {} ],
    [ 'a.b.e', '**.*', {} ],
    [ 'a.b.e', '**.e', {} ],
    [ 'a.b.d', 'a.b.d', {} ],
    [ 'a.b.d', '**.*', {} ],
    [ 'a.b.c', 'a.b.c', {} ],
    [ 'a.b.c', '**.*', {} ],
    [ 'a.b.c', '**.b.c', {} ],
    [ 'a.b', 'a.b', [Object] ],
    [ 'a.b', '**.*', [Object] ],
    [ 'a.b', '*.*', [Object] ],
    [ 'a', '**.*', [Object] ]
  ],
  access: { a: 2, b: 2, e: 2, d: 2, c: 2 }
}
 */

Sweet project!

Was just browsing for competitors to object-scan and this popped up!

Awesome project, I have to look into it in more detail and will definitely add it to the functionality comparison and performance benchmarking suite of object-scan! I'm really looking forward to testing how it compares performance wise!

I have to look at the source code as well. I'm assuming you have a precompilation phase where you build a search tree? Or how does this work internally? What are the next things on the roadmap for this project?

PS: If it wasn't clear from my comment, I'm the author of object-scan

Edit: Read up on how this works internally and can't wait to try it out! It's actually quite different and a cool way of handling the multi path traversal case. However does it require always a full traversal of the entire input?

Fallback does not work with indexOf

I am using nimma in the context of spectral with the fallback option resorting to JSONPath Plus. I have a JSONPath expression that works well in JSONPath Plus. However, this expression is unusable in spectral because nimma raises an error instead of forwarding to the fallback implementation:

Here's the path I try to use:

$..properties[?([email protected] && (@parent.required || []).indexOf(@property) == -1)]

And here's the error I get in spectral:

❯ spectral --version
6.4.1

❯ spectral lint openapi-spec.yaml -r .spectral.yaml -v
Found 72 rules (61 enabled)
Linting /xxx/openapi-spec.yaml
Error running Spectral!
Error #1: (scope.sandbox.parentValue.required || []).indexOf is not a function
          at indexOf(@property) …  …js/core/index.js:66  _rollupPluginBabelH…
          at eval                  …js/core/index.js:66  _rollupPluginBabelH…
          at _traverseBody         …time/traverse.js:13  cb(scope);          
          at _traverse             …time/traverse.js:41  _traverseBody(key, …
          at _traverseBody         …time/traverse.js:17  _traverse(value, sc…

Extension for @jsep-plugin/arrow

Hi Jakub,

I use filter expressions to search for an entry in an array of objects. Is it possible for you to include the @jsep-plugin/arrow? For example, the Array.find() method can also be used as a filter expression in the array.

Here is a small example:

JSONPath: $[?(@.phoneNumbers && @.phoneNumbers.find(phoneNumber => phoneNumber.type.match(/iPh.*/)))]

[{ "firstName": "John", "lastName": "doe", "age": 26, "address": { "streetAddress": "naist street", "city": "Nara", "postalCode": "630-0192" }, "phoneNumbers": [ { "type": "iPhone", "number": "0123-4567-8888" }, { "type": "home", "number": "0123-4567-8910" } ] }]

Best regards,
Rainer

Querying properties that contain #

Tried to query the following JSON document with the JSONPath $..type^[*]^,

{
    "properties": {
        "test#1": {
            "type": "string"
        }
    }
}

I encounted the error: TypeError: Cannot read property 'toString' of undefined. I noticed the error does not occur if property name does not include #.

For demonstration purposes, I made my query (i.e. [*]) trivial here. In my real use-case, I was using a similar JSONPath query with a non-trivial filter [?(...)] in the Spectral context.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.