lloyd / JSONSelect

CSS-like selectors for JSON
http://jsonselect.org
ISC License
1.59k stars 116 forks source link

a means of matching values #15

Closed lloyd closed 13 years ago

lloyd commented 13 years ago

NOTE: This is design exploration for JSONSelect level 3, which is the wild and crazy stuff, not the bread and butter

A major feature missing is the ability to match values, features related to this are by far the most requested for people interested in JSONSelect.

Examples of these types of features exist in different selector engines. Like sizzle where :contains("Lloyd") would find nodes that have textual content where the substring Lloyd is found.

Practical applications of this are all over. Like what if you wanted to get my work email (use case provided by mike hanson):

[
    {
        "type": "home",
        "email": "lloyd@hilaiel.com"
    },
    {
        "type": "work",
        "email": "lloyd@mozilla.com"
    }
 ]

Without the ability to match values, you would have to programmatically iterate over each member, which is rather lame for such a simple task.

One very general solution to the problem that I'm considering is an expression pseudo function. Something that might look like this when attempting to get my work email:

.type:expr(x = "work") ~ .email

That is the email sibling of a type key whose value satisfies the expression x = "work". A similar way to accomplish the same thing would be:

:has(.type:expr(x = "work")) .email

That is, the value of an email property on a node which has a descendant property named "type" that has a value matching x = "work".

I lean toward this :expr() construct because it can be extremely flexible, and the only really unnatural bit is the fact that x is a placeholder that refers to value. I do like that there's precedent for this idea in the nth-*() family of pseudo classes.

There are other ways we could go, such as including more specific pseudo functions for different operations. This is very much what jsonschema does. For instance:

.type:val("work") .email

Rather than a complex expression, this shorthand is basically equivalent, but less flexible. This approach becomes unwieldy and clunky for more complex expressions. Compare:

.salary:expr(80000 < x < 140000)

That is, find the value of a "salary" property that is a number which is less than 140000 and greater than 80000. If you attempted to express this expression with more granular specific pseudo classes you'd have something like:

.salary:less-than(140000):greater-than(80000)

We should be in no rush to close this issue.