UNPKG

14 kBMarkdownView Raw
1JSPath [![Build Status](https://secure.travis-ci.org/dfilatov/jspath.png)](http://travis-ci.org/dfilatov/jspath)
2============
3
4JSPath is a domain-specific language (DSL) that enables you to navigate and find data within your JSON documents. Using JSPath, you can select items of JSON in order to retrieve the data they contain.
5
6JSPath for JSON like an XPath for XML.
7
8It is heavily optimized both for Node.js and modern browsers.
9
10Table of Contents
11-----------------
12 * [Getting Started](#getting-started)
13 * [In the Node.js](#in-the-nodejs)
14 * [In the Browsers](#in-the-browsers)
15 * [Usage](#usage)
16 * [Quick example](#quick-example)
17 * [Documentation](#documentation)
18 * [Location path](#location-path)
19 * [Predicates](#predicates)
20 * [Object predicates](#object-predicates)
21 * [Comparison operators](#comparison-operators)
22 * [String comparison operators](#string-comparison-operators)
23 * [Logical operators](#logical-operators)
24 * [Arithmetic operators](#arithmetic-operators)
25 * [Operator precedence](#operator-precedence)
26 * [Positional predicates](#positional-predicates)
27 * [Multiple predicates](#multiple-predicates)
28 * [Substitutions](#substitutions)
29 * [Result](#result)
30
31Getting Started
32---------------
33###In the Node.js###
34You can install using Node Package Manager (npm):
35
36 npm install jspath
37
38###In the Browsers###
39```html
40<script type="text/javascript" src="jspath.min.js"></script>
41```
42Also RequireJS module format supported.
43
44JSPath has been tested in IE6+, Mozilla Firefox 3+, Chrome 5+, Safari 5+, Opera 10+.
45
46Usage
47-----
48```javascript
49JSPath.apply(path, json);
50// or
51JSPath.apply(path, json, substs);
52```
53where:
54<table>
55 <tr>
56 <th></th>
57 <th>type</th>
58 <th>description</th>
59 <tr>
60 <td>path</td>
61 <td>String</td>
62 <td>path expression</td>
63 </tr>
64 <tr>
65 <td>json</td>
66 <td>any valid JSON</td>
67 <td>input JSON document</td>
68 </tr>
69 <tr>
70 <td>substs</td>
71 <td>Object</td>
72 <td>substitutions (optional)</td>
73 </tr>
74</table>
75
76###Quick example###
77```javascript
78JSPath.apply(
79 '.automobiles{.maker === "Honda" && .year > 2009}.model',
80 {
81 "automobiles" : [
82 { "maker" : "Nissan", "model" : "Teana", "year" : 2011 },
83 { "maker" : "Honda", "model" : "Jazz", "year" : 2010 },
84 { "maker" : "Honda", "model" : "Civic", "year" : 2007 },
85 { "maker" : "Toyota", "model" : "Yaris", "year" : 2008 },
86 { "maker" : "Honda", "model" : "Accord", "year" : 2011 }
87 ],
88 "motorcycles" : [{ "maker" : "Honda", "model" : "ST1300", "year" : 2012 }]
89 });
90```
91Result will be:
92```javascript
93['Jazz', 'Accord']
94```
95
96Documentation
97-------------
98JSPath expression consists of two type of top-level expressions: location path (required) and predicates (optional).
99
100###Location path###
101To select a items in JSPath, you use a location path.
102A location path consists of one or more location steps.
103Every location step starts with dot (.) or two dots (..) depending on the item you're trying to select:
104 * .property &mdash; locates property immediately descended from the context items
105 * ..property &mdash; locates property deeply descended from the context items
106 * . &mdash; locates the context items itself
107
108You can use the wildcard symbol (*) instead of exact name of property:
109 * .* &mdash; locates all properties immediately descended from the context items
110 * ..* &mdash; locates all properties deeply descended from the context items
111
112Also JSPath allow to join several properties:
113 * (.property1 | .property2 | .propertyN) &mdash; locates property1, property2, propertyN immediately descended from the context items
114 * or even (.property1 | .property2.property2_1.property2_1_1) &mdash; locates .property1, .property2.property2_1.property2_1_1 items
115
116Your location path can be absolute or relative.
117If location path starts with the root (^) you are using an absolute location path &mdash; your location path begins from the root items.
118
119Consider the following JSON:
120```javascript
121var doc = {
122 "books" : [
123 {
124 "id" : 1,
125 "title" : "Clean Code",
126 "author" : { "name" : "Robert C. Martin" },
127 "price" : 17.96
128 },
129 {
130 "id" : 2,
131 "title" : "Maintainable JavaScript",
132 "author" : { "name" : "Nicholas C. Zakas" },
133 "price" : 10
134 },
135 {
136 "id" : 3,
137 "title" : "Agile Software Development",
138 "author" : { "name" : "Robert C. Martin" },
139 "price" : 20
140 },
141 {
142 "id" : 4,
143 "title" : "JavaScript: The Good Parts",
144 "author" : { "name" : "Douglas Crockford" },
145 "price" : 15.67
146 }
147 ]
148};
149```
150
151####Examples####
152```javascript
153// find all books authors
154JSPath.apply('.books.author', doc);
155/* [{ name : 'Robert C. Martin' }, { name : 'Nicholas C. Zakas' }, { name : 'Robert C. Martin' }, { name : 'Douglas Crockford' }] */
156
157// find all books author names
158JSPath.apply('.books.author.name', doc);
159/* ['Robert C. Martin', 'Nicholas C. Zakas', 'Robert C. Martin', 'Douglas Crockford' ] */
160
161// find all names in books
162JSPath.apply('.books..name', doc);
163/* ['Robert C. Martin', 'Nicholas C. Zakas', 'Robert C. Martin', 'Douglas Crockford' ] */
164```
165
166###Predicates###
167An JSPath predicate allows you to write very specific rules about the items you'd like to select when constructing your expressions.
168Predicates are filters that restrict the items selected by an location path. There are two possible type of predicates: object and positional.
169
170###Object predicates###
171Object predicates can be used in a path expression to filter a subset of items according to a boolean expressions working on a properties of each item.
172Object predicates are embedded in braces.
173
174Basic expressions in object predicates:
175 * numeric literals (e.g. 1.23)
176 * string literals (e.g. "John Gold")
177 * boolean literals (true/false)
178 * subpathes (e.g. .nestedProp.deeplyNestedProp)
179
180JSPath allows to use in predicate expressions following types of operators:
181 * comparison operators
182 * string comparison operators
183 * logical operators
184 * arithmetic operators
185
186####Comparison operators####
187
188<table>
189 <tr>
190 <td>==</td>
191 <td>Returns is true if both operands are equal</td>
192 <td>.books{.id == "1"}</td>
193 </tr>
194 <tr>
195 <td>===</td>
196 <td>Returns true if both operands are strictly equal with no type conversion</td>
197 <td>.books{.id === 1}</td>
198 </tr>
199 <tr>
200 <td>!=</td>
201 <td>Returns true if the operands are not equal</td>
202 <td>.books{.id != "1"}</td>
203 </tr>
204 <tr>
205 <td>!==</td>
206 <td>Returns true if the operands are not equal and/or not of the same type</td>
207 <td>.books{.id !== 1}</td>
208 </tr>
209 <tr>
210 <td>></td>
211 <td>Returns true if the left operand is greater than the right operand</td>
212 <td>.books{.id > 1}</td>
213 </tr>
214 <tr>
215 <td>>=</td>
216 <td>Returns true if the left operand is greater than or equal to the right operand</td>
217 <td>.books{.id >= 1}</td>
218 </tr>
219 <tr>
220 <td>&lt;</td>
221 <td>Returns true if the left operand is less than the right operand</td>
222 <td>.books{.id &lt; 1}</td>
223 </tr>
224 <tr>
225 <td>&lt;=</td>
226 <td>Returns true if the left operand is less than or equal to the right operand</td>
227 <td>.books{.id &lt;= 1}</td>
228 </tr>
229</table>
230
231Comparison rules:
232 * if both operands to be compared are arrays, then the comparison will be
233true if there is a element in the first array and a element in the
234second array such that the result of performing the comparison of the two elements is true
235 * if one operand is array and another is not, then the comparison will be true if there is element in
236array such that the result of performing the comparison of element and another operand is true
237 * primitives to be compared as usual javascript primitives
238
239If both operands are strings, also available additional comparison operators:
240####String comparison operators####
241<table>
242 <tr>
243 <td>==</td>
244 <td>Like an usual '==' but case insensitive</td>
245 <td>.books{.title == "clean code"}</td>
246 </tr>
247 <tr>
248 <td>^==</td>
249 <td>Returns true if left operand value beginning with right operand value</td>
250 <td>.books{.title ^== "Javascript"}</td>
251 </tr>
252 <tr>
253 <td>^=</td>
254 <td>Like a '^==' but case insensitive</td>
255 <td>.books{.title ^= "javascript"}</td>
256 </tr>
257 <tr>
258 <td>$==</td>
259 <td>Returns true if left operand value ending with right operand value</td>
260 <td>.books{.title $== "Javascript"}</td>
261 </tr>
262 <tr>
263 <td>$=</td>
264 <td>Like a '$==' but case insensitive</td>
265 <td>.books{.title $= "javascript"}</td>
266 </tr>
267 <tr>
268 <td>*==</td>
269 <td>Returns true if left operand value contains right operand value</td>
270 <td>.books{.title *== "Javascript"}</td>
271 </tr>
272 <tr>
273 <td>*=</td>
274 <td>Like a '*==' but case insensitive</td>
275 <td>.books{.title *= "javascript"}</td>
276 </tr>
277</table>
278
279####Logical operators####
280
281<table>
282 <tr>
283 <td>&&</td>
284 <td>Returns true if both operands are true</td>
285 <td>.books{.price > 19 && .author.name === "Robert C. Martin"}</td>
286 </tr>
287 <tr>
288 <td>||</td>
289 <td>Returns true if either operand is true</td>
290 <td>.books{.title === "Maintainable JavaScript" || .title === "Clean Code"}</td>
291 </tr>
292 <tr>
293 <td>!</td>
294 <td>Returns true if operand is false</td>
295 <td>.books{!.title}</td>
296 </tr>
297</table>
298
299Logical operators convert their operands to boolean values using next rules:
300 * if operand is array (as you remember result of applying subpath also array):
301 * if length of array greater than zero, result will be true
302 * else result will be false
303 * Casting with double NOT (!!) javascript operator used in any other cases.
304
305####Arithmetic operators####
306
307<table>
308 <tr>
309 <td>+</td>
310 <td>addition</td>
311 </tr>
312 <tr>
313 <td>-</td>
314 <td>subtraction</td>
315 </tr>
316 <tr>
317 <td>*</td>
318 <td>multiplication</td>
319 </tr>
320 <tr>
321 <td>/</td>
322 <td>division</td>
323 </tr>
324 <tr>
325 <td>%</td>
326 <td>modulus</td>
327 </tr>
328</table>
329
330####Operator precedence####
331<table>
332 <tr>
333 <td>1 (top)</td>
334 <td>! -<sup>unary</sup></td>
335 </tr>
336 <tr>
337 <td>2</td>
338 <td>* / %</td>
339 </tr>
340 <tr>
341 <td>3</td>
342 <td>+ -<sup>binary</sup></td>
343 </tr>
344 <tr>
345 <td>4</td>
346 <td>< <= > >=</td>
347 </tr>
348 <tr>
349 <td>5</td>
350 <td>== === != !== ^= ^== $== $= *= *==</td>
351 </tr>
352 <tr>
353 <td>6</td>
354 <td>&&</td>
355 </tr>
356 <tr>
357 <td>7</td>
358 <td>||</td>
359 </tr>
360</table>
361
362Parentheses are used to explicitly denote precedence by grouping parts of an expression that should be evaluated first.
363
364####Examples####
365```javascript
366// find all book titles whose author is Robert C. Martin
367JSPath.apply('.books{.author.name === "Robert C. Martin"}.title', doc);
368/* ['Clean Code', 'Agile Software Development'] */
369
370// find all book titles with price less than 17
371JSPath.apply('.books{.price < 17}.title', doc);
372/* ['Maintainable JavaScript', 'JavaScript: The Good Parts'] */
373```
374
375###Positional predicates###
376Positional predicates allows you to filter items by their context position.
377Positional predicates are always embedded in square brackets.
378
379There are four available forms:
380 * [ _index_ ] &mdash; returns _index_-positioned item in context (first item is at index 0), e.g. [3] returns fourth item in context
381 * [ _index_ : ] &mdash; returns items whose index in context is greater or equal to _index_, e.g. [2:] returns items whose index in context is greater or equal to 2
382 * [ : _index_ ] &mdash; returns items whose index in context is smaller than _index_, e.g. [:5] returns first five items in context
383 * [ _indexFrom_ : _indexTo_ ] &mdash; returns items whose index in context is greater or equal to _indexFrom_ and smaller than _indexTo_, e.g. [2:5] returns three items with indices 2, 3 and 4
384
385Also you can use negative position numbers:
386 * [-1] &mdash; returns last item in context
387 * [-3:] &mdash; returns last three items in context
388
389####Examples####
390```javascript
391// find first book title
392JSPath.apply('.books[0].title', doc);
393/* ['Clean Code'] */
394
395// find first title of books
396JSPath.apply('.books.title[0]', doc);
397/* 'Clean Code' */
398
399// find last book title
400JSPath.apply('.books[-1].title', doc);
401/* ['JavaScript: The Good Parts'] */
402
403// find two first book titles
404JSPath.apply('.books[:2].title', doc);
405/* ['Clean Code', 'Maintainable JavaScript'] */
406
407// find two last book titles
408JSPath.apply('.books[-2:].title', doc);
409/* ['Agile Software Development', 'JavaScript: The Good Parts'] */
410
411// find two book titles from second position
412JSPath.apply('.books[1:3].title', doc);
413/* ['Maintainable JavaScript', 'Agile Software Development'] */
414```
415
416###Multiple predicates###
417You can use more than one predicate. The result will contain only the items that match all the predicates.
418
419####Examples####
420```javascript
421// find first book name whose price less than 15 and greater than 5
422JSPath.apply('.books{.price < 15}{.price > 5}[0].title', doc);
423/* ['Maintainable JavaScript'] */
424```
425
426###Substitutions###
427Substitutions allows you to use a runtime-evaluated values in predicates.
428
429####Examples####
430```javascript
431var path = '.books{.author.name === $author}.title';
432
433// find book name whose author Nicholas C. Zakas
434JSPath.apply(path, doc, { author : 'Nicholas C. Zakas' });
435/* ['Maintainable JavaScript'] */
436
437// find books name whose authors Robert C. Martin or Douglas Crockford
438JSPath.apply(path, doc, { author : ['Robert C. Martin', 'Douglas Crockford'] });
439/* ['Clean Code', 'Agile Software Development', 'JavaScript: The Good Parts'] */
440```
441
442###Result###
443Result of applying JSPath is always an array (empty, if nothing found), excluding case when the last predicate in top-level expression is positional predicate with the exact index (e.g. [0], [5], [-1]).
444In this case, result is item at the specified index (accordingly _undefined_, if no item).