CSS Selectors for JSON - GistLabs/mechanize GitHub Wiki

CSS Selectors, a JSON query language

CSS Selectors are an elegant mix of simplicity and power. They are also nearly ubiquitous to everyone involved in web development. This page describes how CSS Selectors are made available to searching JSON.

Examples

	"doc": {
		"uri": "/id/42",
		"rel": "self",
		"next": {
			"uri": "/id/43",
			"about": {
				"href": "a"
			}
		},
		"prev": {
			"uri": "/id/41",
			"about": {
				"href": "a"
			}
		},
		"line-items": [
			{ "uri": "/item/{id}", "types": "type1", "id": "3d4"},
			{ "uri": "/item/{id}", "types": "type1 type2", "id": "ab2"},
			{ "uri": "/item/{id}", "types": "type3", "id": "54e"}
		]
	}	

Here are some examples of applying CCS Selectors to this JSON:

  • find next .getAttribute("uri") is /id/43
  • find doc next is same result as next in this case
  • findAll [href] size is 2, the "about" nodes
  • find doc .find prev .getAttribute("uri") is /id/41
  • findAll doc line-items[types~="type1"] size is 2
  • findAll doc line-items[types~="type2"] size is 1

Flexibility Built-in

One important reason to use a query language to find content in a document type is the flexibility it enable for evolvable systems.

Consider the following CSS Selector: doc line-items[types~="type2"]. This will function exactly the same even if the JSON document was restructured like this:

	"doc": {
		"_links": [
			{"rel": "self", "uri": "/id/42"},
			{"rel": "next", "uri": "/id/43", "about": {"href": "a"}},
			{"rel": "prev", "uri": "/id/41", "about": {"href": "a"}}
		],
		"_properties": [
			{"line-items": [
				{ "uri": "/item/{id}", "types": "type1", "id": "3d4"},
				{ "uri": "/item/{id}", "types": "type1 type2", "id": "ab2"},
				{ "uri": "/item/{id}", "types": "type3", "id": "54e"}
			]}
		]
	}	

Not all of the selectors are quite so flexible. Notice that doc next would need to be changed, perhaps to doc [rel="next"]. For hyperlink definitions see Finding JSON Links to learn how we handle this flexibility.

The benefit is in creating extra degrees of freedom for the server/producer to evolve and change, without causing breaking changes to clients/consumers.

Implementation

This implementation is is based on a wrapping object model around a standard JSON parser.

No efforts at optimization have been undertaken, instead all focus is on testing ideas for merit.