-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #25 from spenceralger/saved_search
Saved search
- Loading branch information
Showing
28 changed files
with
1,336 additions
and
330 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
{ | ||
"name": "jsonpath", | ||
"homepage": "https://github.com/s3u/JSONPath", | ||
"_release": "308ef21860", | ||
"_resolution": { | ||
"type": "branch", | ||
"branch": "master", | ||
"commit": "308ef21860ae21584c0f808d67cf63006101149a" | ||
}, | ||
"_source": "git://github.com/s3u/JSONPath.git", | ||
"_target": "*", | ||
"_originalSource": "jsonpath" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
*.iml | ||
.DS_Store | ||
.idea | ||
temp | ||
node_modules | ||
pids | ||
reports | ||
target | ||
*.log |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
node_modules | ||
test |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
language: node_js | ||
node_js: | ||
- 0.6 | ||
- 0.8 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
|
||
## Oct 23, 2013 | ||
|
||
* Support for parent selection via `^` | ||
* Access current path via `@path` in test statements | ||
* Allowing for multi-statement evals | ||
* Performance improvements | ||
* Version 0.10 | ||
|
||
## Mar 28, 2012 | ||
|
||
* Support a sandbox arg to eval | ||
* Use vm.runInNewContext in place of eval | ||
* Version 0.9.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
JSONPath [![build status](https://secure.travis-ci.org/s3u/JSONPath.png)](http://travis-ci.org/s3u/JSONPath) | ||
======== | ||
|
||
Analyse, transform, and selectively extract data from JSON documents (and JavaScript objects). | ||
|
||
Install | ||
------- | ||
|
||
npm install JSONPath | ||
|
||
Usage | ||
----- | ||
|
||
In node.js: | ||
|
||
```js | ||
var jsonPath = require('JSONPath'); | ||
jsonPath.eval(obj, path); | ||
``` | ||
|
||
For browser usage you can directly include `lib/jsonpath.js`, no browserify | ||
magic necessary: | ||
|
||
```html | ||
<script type="text/javascript" src="lib/jsonpath.js"></script> | ||
<script type="text/javascript"> | ||
jsonPath.eval(obj, path); | ||
</script> | ||
``` | ||
|
||
Examples | ||
-------- | ||
|
||
Given the following JSON, taken from http://goessner.net/articles/JsonPath/ : | ||
|
||
```json | ||
{ | ||
"store": { | ||
"book": [ | ||
{ | ||
"category": "reference", | ||
"author": "Nigel Rees", | ||
"title": "Sayings of the Century", | ||
"price": 8.95 | ||
}, | ||
{ | ||
"category": "fiction", | ||
"author": "Evelyn Waugh", | ||
"title": "Sword of Honour", | ||
"price": 12.99 | ||
}, | ||
{ | ||
"category": "fiction", | ||
"author": "Herman Melville", | ||
"title": "Moby Dick", | ||
"isbn": "0-553-21311-3", | ||
"price": 8.99 | ||
}, | ||
{ | ||
"category": "fiction", | ||
"author": "J. R. R. Tolkien", | ||
"title": "The Lord of the Rings", | ||
"isbn": "0-395-19395-8", | ||
"price": 22.99 | ||
} | ||
], | ||
"bicycle": { | ||
"color": "red", | ||
"price": 19.95 | ||
} | ||
} | ||
} | ||
``` | ||
|
||
|
||
XPath | JSONPath | Result | ||
------------------- | ---------------------- | ------------------------------------- | ||
/store/book/author | $.store.book[*].author | the authors of all books in the store | ||
//author | $..author | all authors | ||
/store/* | $.store.* | all things in store, which are some books and a red bicycle. | ||
/store//price | $.store..price | the price of everything in the store. | ||
//book[3] | $..book[2] | the third book | ||
//book[last()] | $..book[(@.length-1)] | the last book in order. | ||
| $..book[-1:] | | ||
//book[position()<3]| $..book[0,1] | the first two books | ||
| $..book[:2] | | ||
//book[isbn] | $..book[?(@.isbn)] | filter all books with isbn number | ||
//book[price<10] | $..book[?(@.price<10)] | filter all books cheapier than 10 | ||
//*[price>19]/.. | $..[?(@.price>19)]^ | categories with things more expensive than 19 | ||
//* | $..* | all Elements in XML document. All members of JSON structure. | ||
|
||
Development | ||
----------- | ||
|
||
Running the tests on node: `npm test`. For in-browser tests: | ||
|
||
* Ensure that nodeunit is browser-compiled: `cd node_modules/nodeunit; make browser;` | ||
* Serve the js/html files: | ||
|
||
```sh | ||
node -e "require('http').createServer(function(req,res) { \ | ||
var s = require('fs').createReadStream('.' + req.url); \ | ||
s.pipe(res); s.on('error', function() {}); }).listen(8082);" | ||
``` | ||
* To run the tests visit [http://localhost:8082/test/test.html](). | ||
|
||
|
||
License | ||
------- | ||
|
||
[MIT License](http://www.opensource.org/licenses/mit-license.php). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
/* JSONPath 0.8.0 - XPath for JSON | ||
* | ||
* Copyright (c) 2007 Stefan Goessner (goessner.net) | ||
* Licensed under the MIT (MIT-LICENSE.txt) licence. | ||
*/ | ||
|
||
var isNode = false; | ||
(function(exports, require) { | ||
|
||
// Keep compatibility with old browsers | ||
if (!Array.isArray) { | ||
Array.isArray = function(vArg) { | ||
return Object.prototype.toString.call(vArg) === "[object Array]"; | ||
}; | ||
} | ||
|
||
// Make sure to know if we are in real node or not (the `require` variable | ||
// could actually be require.js, for example. | ||
var isNode = typeof module !== 'undefined' && !!module.exports; | ||
|
||
var vm = isNode ? | ||
require('vm') : { | ||
runInNewContext: function(expr, context) { with (context) return eval(expr); } | ||
}; | ||
exports.eval = jsonPath; | ||
|
||
var cache = {}; | ||
|
||
function push(arr, elem) { arr = arr.slice(); arr.push(elem); return arr; } | ||
function unshift(elem, arr) { arr = arr.slice(); arr.unshift(elem); return arr; } | ||
|
||
function jsonPath(obj, expr, arg) { | ||
var P = { | ||
resultType: arg && arg.resultType || "VALUE", | ||
flatten: arg && arg.flatten || false, | ||
wrap: (arg && arg.hasOwnProperty('wrap')) ? arg.wrap : true, | ||
sandbox: (arg && arg.sandbox) ? arg.sandbox : {}, | ||
normalize: function(expr) { | ||
if (cache[expr]) return cache[expr]; | ||
var subx = []; | ||
var normalized = expr.replace(/[\['](\??\(.*?\))[\]']/g, function($0,$1){return "[#"+(subx.push($1)-1)+"]";}) | ||
.replace(/'?\.'?|\['?/g, ";") | ||
.replace(/(;)?(\^+)(;)?/g, function(_, front, ups, back) { return ';' + ups.split('').join(';') + ';'; }) | ||
.replace(/;;;|;;/g, ";..;") | ||
.replace(/;$|'?\]|'$/g, ""); | ||
var exprList = normalized.split(';').map(function(expr) { | ||
var match = expr.match(/#([0-9]+)/); | ||
return !match || !match[1] ? expr : subx[match[1]]; | ||
}) | ||
return cache[expr] = exprList; | ||
}, | ||
asPath: function(path) { | ||
var x = path, p = "$"; | ||
for (var i=1,n=x.length; i<n; i++) | ||
p += /^[0-9*]+$/.test(x[i]) ? ("["+x[i]+"]") : ("['"+x[i]+"']"); | ||
return p; | ||
}, | ||
trace: function(expr, val, path) { | ||
// no expr to follow? return path and value as the result of this trace branch | ||
if (!expr.length) return [{path: path, value: val}]; | ||
|
||
var loc = expr[0], x = expr.slice(1); | ||
// the parent sel computation is handled in the frame above using the | ||
// ancestor object of val | ||
if (loc === '^') return path.length ? [{path: path.slice(0,-1), expr: x, isParentSelector: true}] : []; | ||
|
||
// we need to gather the return value of recursive trace calls in order to | ||
// do the parent sel computation. | ||
var ret = []; | ||
function addRet(elems) { ret = ret.concat(elems); } | ||
|
||
if (val && val.hasOwnProperty(loc)) // simple case, directly follow property | ||
addRet(P.trace(x, val[loc], push(path, loc))); | ||
else if (loc === "*") { // any property | ||
P.walk(loc, x, val, path, function(m,l,x,v,p) { | ||
addRet(P.trace(unshift(m, x), v, p)); }); | ||
} | ||
else if (loc === "..") { // all chid properties | ||
addRet(P.trace(x, val, path)); | ||
P.walk(loc, x, val, path, function(m,l,x,v,p) { | ||
if (typeof v[m] === "object") | ||
addRet(P.trace(unshift("..", x), v[m], push(p, m))); | ||
}); | ||
} | ||
else if (loc[0] === '(') { // [(expr)] | ||
addRet(P.trace(unshift(P.eval(loc, val, path[path.length], path),x), val, path)); | ||
} | ||
else if (loc.indexOf('?(') === 0) { // [?(expr)] | ||
P.walk(loc, x, val, path, function(m,l,x,v,p) { | ||
if (P.eval(l.replace(/^\?\((.*?)\)$/,"$1"),v[m],m, path)) | ||
addRet(P.trace(unshift(m,x),v,p)); | ||
}); | ||
} | ||
else if (loc.indexOf(',') > -1) { // [name1,name2,...] | ||
for (var parts = loc.split(','), i = 0; i < parts.length; i++) | ||
addRet(P.trace(unshift(parts[i], x), val, path)); | ||
} | ||
else if (/^(-?[0-9]*):(-?[0-9]*):?([0-9]*)$/.test(loc)) { // [start:end:step] python slice syntax | ||
addRet(P.slice(loc, x, val, path)); | ||
} | ||
|
||
// we check the resulting values for parent selections. for parent | ||
// selections we discard the value object and continue the trace with the | ||
// current val object | ||
return ret.reduce(function(all, ea) { | ||
return all.concat(ea.isParentSelector ? P.trace(ea.expr, val, ea.path) : [ea]); | ||
}, []); | ||
}, | ||
walk: function(loc, expr, val, path, f) { | ||
if (Array.isArray(val)) | ||
for (var i = 0, n = val.length; i < n; i++) | ||
f(i, loc, expr, val, path); | ||
else if (typeof val === "object") | ||
for (var m in val) | ||
if (val.hasOwnProperty(m)) | ||
f(m, loc, expr, val, path); | ||
}, | ||
slice: function(loc, expr, val, path) { | ||
if (!Array.isArray(val)) return; | ||
var len = val.length, parts = loc.split(':'), | ||
start = (parts[0] && parseInt(parts[0])) || 0, | ||
end = (parts[1] && parseInt(parts[1])) || len, | ||
step = (parts[2] && parseInt(parts[2])) || 1; | ||
start = (start < 0) ? Math.max(0,start+len) : Math.min(len,start); | ||
end = (end < 0) ? Math.max(0,end+len) : Math.min(len,end); | ||
var ret = []; | ||
for (var i = start; i < end; i += step) | ||
ret = ret.concat(P.trace(unshift(i,expr), val, path)); | ||
return ret; | ||
}, | ||
eval: function(code, _v, _vname, path) { | ||
if (!$ || !_v) return false; | ||
if (code.indexOf("@path") > -1) { | ||
P.sandbox["_path"] = P.asPath(path.concat([_vname])); | ||
code = code.replace(/@path/g, "_path"); | ||
} | ||
if (code.indexOf("@") > -1) { | ||
P.sandbox["_v"] = _v; | ||
code = code.replace(/@/g, "_v"); | ||
} | ||
try { | ||
return vm.runInNewContext(code, P.sandbox); | ||
} | ||
catch(e) { | ||
console.log(e); | ||
throw new Error("jsonPath: " + e.message + ": " + code); | ||
} | ||
} | ||
}; | ||
|
||
var $ = obj; | ||
var resultType = P.resultType.toLowerCase(); | ||
if (expr && obj && (resultType == "value" || resultType == "path")) { | ||
var exprList = P.normalize(expr); | ||
if (exprList[0] === "$" && exprList.length > 1) exprList.shift(); | ||
var result = P.trace(exprList, obj, ["$"]); | ||
result = result.filter(function(ea) { return ea && !ea.isParentSelector; }); | ||
if (!result.length) return P.wrap ? [] : false; | ||
if (result.length === 1 && !P.wrap && !Array.isArray(result[0].value)) return result[0][resultType] || false; | ||
return result.reduce(function(result, ea) { | ||
var valOrPath = ea[resultType]; | ||
if (resultType === 'path') valOrPath = P.asPath(valOrPath); | ||
if (P.flatten && Array.isArray(valOrPath)) { | ||
result = result.concat(valOrPath); | ||
} else { | ||
result.push(valOrPath); | ||
} | ||
return result; | ||
}, []); | ||
} | ||
} | ||
})(typeof exports === 'undefined' ? this['jsonPath'] = {} : exports, typeof require == "undefined" ? null : require); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
{ | ||
"author": "Stefan Goessner", | ||
"name": "JSONPath", | ||
"description": "A JS implementation of JSONPath", | ||
"contributors": [ | ||
{ | ||
"name": "Prof. Gössner", | ||
"email": "[email protected]" | ||
}, | ||
{ | ||
"name": "Subbu Allamaraju", | ||
"email": "[email protected]" | ||
}, | ||
{ | ||
"name": "Mike Brevoort", | ||
"email": "[email protected]" | ||
}, | ||
{ | ||
"name": "Robert Krahn", | ||
"email": "[email protected]" | ||
} | ||
], | ||
"version": "0.10.0", | ||
"repository": { | ||
"type": "git", | ||
"url": "git://github.com/s3u/JSONPath.git" | ||
}, | ||
"main": "./lib/jsonpath", | ||
"dependencies": { | ||
"underscore": "*" | ||
}, | ||
"devDependencies": { | ||
"nodeunit": "*" | ||
}, | ||
"scripts": {"test": "node_modules/nodeunit/bin/nodeunit test/test.*.js"} | ||
} |
Oops, something went wrong.