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
:has()
has been promoted from maybe to is status in the docs: http://jsonselect.org/#docs/overview