dfilatov / jspath

DSL that enables you to navigate and find data within your JSON documents
MIT License
553 stars 40 forks source link

Selecting variables and from variables #30

Closed hoho closed 9 years ago

hoho commented 9 years ago

I can do something like JSPath.apply('.aa{$bb === 2}', {aa: 1}, {bb: 2}).

It would be nice to be able to do something like JSPath.apply('.aa{$bb.cc === 2}', {aa: 1}, {bb: {cc: 2}}) and JSPath.apply('$aa', {}, {aa: [1,2,3]}).

dfilatov commented 9 years ago

@hoho I tried to understand your examples, but I didn't manage. Why do you need to select .aa with predicate ($bb.cc === 2}) on another object? Maybe you could you provide more realistic ones?

hoho commented 9 years ago

JSPath.apply('$param', {}, {param: {aa: 11, bb: 22}} -> {aa: 11, bb: 22} JSPath.apply('$param.aa', {}, {param: {aa: 11, bb: 22}} -> [11] JSPath.apply('$param.*', {}, {param: {aa: 11, bb: 22}} -> [11, 22] JSPath.apply('.cc | $param.bb', {cc: 33}, {param: {aa: 11, bb: 22}} -> [33, 22]

dfilatov commented 9 years ago

Let's take your first example: JSPath.apply('$param', {}, {param: {aa: 11, bb: 22}}) -> {aa: 11, bb: 22} At first $param inside path is replaced by {param: {aa: 11, bb: 22}}. Then the resulting path (as object?) is applied to {}. What does it mean?

It seems I've actually been missing something you want to achieve.

hoho commented 9 years ago

This is an example from readme:

var path = '.books{.author.name === $author}.title';
JSPath.apply(path, doc, { author : ['Robert C. Martin', 'Douglas Crockford'] });
/* ['Clean Code', 'Agile Software Development', 'JavaScript: The Good Parts'] */

I want something like XPath variables.

var path = '.books{.author.name === $author | .author.name === $author2}.title | $data..key1';
JSPath.apply(path, doc, {
    author: 'Robert C. Martin',
    author2: 'Douglas Crockford',
    data: {
        key1: 123,
        key2: {
            key1: 435
        }
    }
});
/* ['Clean Code', 'Agile Software Development', 'JavaScript: The Good Parts', 123, 456] */

Or just an ability to select variable value:

JSPath.apply('$author', doc, {author : ['Robert C. Martin', 'Douglas Crockford']});
/* ['Robert C. Martin', 'Douglas Crockford'] */

JSPath.apply('$author[1]', doc, {author : ['Robert C. Martin', 'Douglas Crockford']});
/* 'Douglas Crockford' */
dfilatov commented 9 years ago

Why don't you want to have data as data, not as variable?

JSPath.apply('.author[1]', {author : ['Robert C. Martin', 'Douglas Crockford']});
/* 'Douglas Crockford' */
hoho commented 9 years ago

I do want to have it and I'm having it. But just for the same reason XSLT variables exist — context data is not always enough. I'm trying to make a DSL to build JSON trees from other JSON trees. I'm starting with something like this: https://github.com/hoho/dryad. And I sense that an ability to address variables from JSPath expressions would be really useful.

dfilatov commented 9 years ago

Why is context data not enough? You're able to construct context as needed, something like this:

JSPath.apply(
    path,
    {
        mainData : data
        otherData : otherData,
        otherData2 : otherData2
    });

Then you can refer to any part of data within path via absolute locator: ^.mainData, ^.otherData, ^.otherData2. Thus you don't need to split your data to data and variables.

hoho commented 9 years ago

That's not it semantically. I have the context data and I have some other datas, from other sources, dynamically constructed. Just the same to XSLT — you have the context XML tree and you have variables you can construct on the run and pass as the parameters to other templates. For example, tree2 function from https://github.com/hoho/dryad readme (I've added some comments) — there is the context data and there are arguments. It would be semantically straightforward to address arguments by the same names in JSPath queries and to query the context data with direct JSPath queries.

hoho commented 9 years ago

Another good reason is to pass more complex environment structures. Something like:

var path = '.books{.author.name ^== $author.first}.title';
JSPath.apply(path, doc, {author: [{first: 'Robert', last: 'C. Martin'}, {first: 'Douglas', last: 'Crockford'}]});

Yes, the context data could be rearranged somehow. But I'm about to make a tool for rearranging the data and it is strange to rearrange the data for the tool that aims to rearrange the data.

I guess it is logical to have this, especially when XPath was the source of inspiration (a variable could have a nodeset value and in such case this nodeset elements are addressable from XPath expressions).

And just to have it straight — you object because you want to see a good use case for the feature or you object because it is hard to implement? :)

dfilatov commented 9 years ago

At first look it's not difficult to implement. I'm just trying to realise that it really needs to do :)

dfilatov commented 9 years ago

Will be implemented in 0.3

hoho commented 9 years ago

👍

dfilatov commented 9 years ago

@hoho I've released 0.3.0, could you check whether it works as you expected?

hoho commented 9 years ago

Cool! I'm onto testing it.

hoho commented 9 years ago

From the first sight looks as expected. #29 too. Thanks a lot!

dfilatov commented 9 years ago

@hoho Thank you for participating!