This perhaps deserves a blog post, but whatever.
The challenge: What if you wanted to determine what level my Bulgarian language skills were at? Using this sample document:
{
"name": {
"first": "Lloyd",
"last": "Hilaiel"
},
"favoriteColor": "yellow",
"languagesSpoken": [
{
"language": "Bulgarian",
"level": "advanced"
},
{
"language": "English",
"level": "native"
},
{
"language": "Spanish",
"level": "beginner"
}
],
"seatingPreference": [
"window",
"aisle"
],
"drinkPreference": [
"whiskey",
"beer",
"wine"
],
"weight": 172
}
How would you craft a CSS-like selector to extract the value of the key level
contained in an object where language
has a value of Bulgarian
? (i.e. match the string advanced
)
NOW STOP. Don't read any more of this gist. Go think about it. Do you know any CSS that should apply here?
By this time, you've already thought of your own answer. A few possible (sometimes complimentary) routes are in my head.
The first solution is general and has precedent in jquery/sizzle. Specifically :has()
and :contains()
inspired by jquery. But maybe we'd rename :contains
to :val
.
.languagesSpoken :has(.language:val('Bulgarian')) .level
The other route could repurpose attribute selectors to say that they match children
.languagesSpoken object[language="Bulgarian"] .level
Note that the former is potentially much more flexible because the :has() pseudo function can take complete selectors.
Note also that the latter could be a syntactic abbreviation for the former. This is in
fact how things like :first-child
and :last-child
are implemented in the reference implementation.
Another option could use the sibling combinator from css3:
.languagesSpoken .language:val('Bulgarian') ~ .level
The latter could be more abbreviated even, exactly like in CSS :
You can also handle multiple checks like in CSS :
How to handle this with :has ?
?
I like the potential flexibility of :has with inner selectors but only having this one to check properties would imho make JSONSelect unnecessarily more verbose, and 'diverge' from CSS, for the likely most common use cases (property presence check, property value check and other simple CSS attribute selectors).