Comparing version 0.1.3 to 0.1.4
module.exports = { | ||
identifier: "[a-zA-Z_]+[a-zA-Z0-9_]*", | ||
integer: "-?(?:[0-9]|[1-9][0-9]+)", | ||
integer: "-?(?:0|[1-9][0-9]*)", | ||
qq_string: "\"(?:\\\\[\"bfnrt/\\\\]|\\\\u[a-fA-F0-9]{4}|[^\"\\\\])*\"", | ||
q_string: "'(?:\\\\[\'bfnrt/\\\\]|\\\\u[a-fA-F0-9]{4}|[^\'\\\\])*'" | ||
}; |
var dict = require('./dict'); | ||
var grammar = { | ||
lex: { | ||
macros: { | ||
@@ -9,2 +11,3 @@ esc: "\\\\", | ||
}, | ||
rules: [ | ||
@@ -32,66 +35,67 @@ ["\\$", "return 'DOLLAR'"], | ||
JSON_PATH: [ | ||
[ 'DOLLAR', 'yy.ast.set({ expression: { type: "root", value: $1 } }); yy.ast.unshift(); return yy.ast.yield()' ], | ||
[ 'DOLLAR PATH_COMPONENTS', 'yy.ast.set({ expression: { type: "root", value: $1 } }); yy.ast.unshift(); return yy.ast.yield()' ], | ||
[ 'LEADING_CHILD_MEMBER_EXPRESSION', 'yy.ast.unshift(); return yy.ast.yield()' ], | ||
[ 'LEADING_CHILD_MEMBER_EXPRESSION PATH_COMPONENTS', 'yy.ast.set({ operation: "member", scope: "child", expression: { type: "identifier", value: $1 }}); yy.ast.unshift(); return yy.ast.yield()' ] ], | ||
JSON_PATH: [ | ||
[ 'DOLLAR', 'yy.ast.set({ expression: { type: "root", value: $1 } }); yy.ast.unshift(); return yy.ast.yield()' ], | ||
[ 'DOLLAR PATH_COMPONENTS', 'yy.ast.set({ expression: { type: "root", value: $1 } }); yy.ast.unshift(); return yy.ast.yield()' ], | ||
[ 'LEADING_CHILD_MEMBER_EXPRESSION', 'yy.ast.unshift(); return yy.ast.yield()' ], | ||
[ 'LEADING_CHILD_MEMBER_EXPRESSION PATH_COMPONENTS', 'yy.ast.set({ operation: "member", scope: "child", expression: { type: "identifier", value: $1 }}); yy.ast.unshift(); return yy.ast.yield()' ] ], | ||
PATH_COMPONENTS: [ | ||
[ 'PATH_COMPONENT', '' ], | ||
[ 'PATH_COMPONENTS PATH_COMPONENT', '' ] ], | ||
PATH_COMPONENTS: [ | ||
[ 'PATH_COMPONENT', '' ], | ||
[ 'PATH_COMPONENTS PATH_COMPONENT', '' ] ], | ||
PATH_COMPONENT: [ | ||
[ 'MEMBER_COMPONENT', 'yy.ast.set({ operation: "member" }); yy.ast.push()' ], | ||
[ 'SUBSCRIPT_COMPONENT', 'yy.ast.set({ operation: "subscript" }); yy.ast.push() ' ] ], | ||
PATH_COMPONENT: [ | ||
[ 'MEMBER_COMPONENT', 'yy.ast.set({ operation: "member" }); yy.ast.push()' ], | ||
[ 'SUBSCRIPT_COMPONENT', 'yy.ast.set({ operation: "subscript" }); yy.ast.push() ' ] ], | ||
MEMBER_COMPONENT: [ | ||
[ 'CHILD_MEMBER_COMPONENT', 'yy.ast.set({ scope: "child" })' ], | ||
[ 'DESCENDANT_MEMBER_COMPONENT', 'yy.ast.set({ scope: "descendant" })' ] ], | ||
MEMBER_COMPONENT: [ | ||
[ 'CHILD_MEMBER_COMPONENT', 'yy.ast.set({ scope: "child" })' ], | ||
[ 'DESCENDANT_MEMBER_COMPONENT', 'yy.ast.set({ scope: "descendant" })' ] ], | ||
CHILD_MEMBER_COMPONENT: [ | ||
[ 'DOT MEMBER_EXPRESSION', '' ] ], | ||
CHILD_MEMBER_COMPONENT: [ | ||
[ 'DOT MEMBER_EXPRESSION', '' ] ], | ||
LEADING_CHILD_MEMBER_EXPRESSION: [ | ||
[ 'MEMBER_EXPRESSION', 'yy.ast.set({ scope: "child", operation: "member" })' ] ], | ||
LEADING_CHILD_MEMBER_EXPRESSION: [ | ||
[ 'MEMBER_EXPRESSION', 'yy.ast.set({ scope: "child", operation: "member" })' ] ], | ||
DESCENDANT_MEMBER_COMPONENT: [ | ||
[ 'DOT_DOT MEMBER_EXPRESSION', '' ] ], | ||
DESCENDANT_MEMBER_COMPONENT: [ | ||
[ 'DOT_DOT MEMBER_EXPRESSION', '' ] ], | ||
MEMBER_EXPRESSION: [ | ||
[ 'STAR', 'yy.ast.set({ expression: { type: "wildcard", value: $1 } })' ], | ||
[ 'IDENTIFIER', 'yy.ast.set({ expression: { type: "identifier", value: $1 } })' ], | ||
[ 'SCRIPT_EXPRESSION', 'yy.ast.set({ expression: { type: "script_expression", value: $1 } })' ], | ||
[ 'INTEGER', 'yy.ast.set({ expression: { type: "numeric_literal", value: parseInt($1) } })' ], | ||
[ 'END', '' ] ], | ||
MEMBER_EXPRESSION: [ | ||
[ 'STAR', 'yy.ast.set({ expression: { type: "wildcard", value: $1 } })' ], | ||
[ 'IDENTIFIER', 'yy.ast.set({ expression: { type: "identifier", value: $1 } })' ], | ||
[ 'SCRIPT_EXPRESSION', 'yy.ast.set({ expression: { type: "script_expression", value: $1 } })' ], | ||
[ 'INTEGER', 'yy.ast.set({ expression: { type: "numeric_literal", value: parseInt($1) } })' ], | ||
[ 'END', '' ] ], | ||
SUBSCRIPT_COMPONENT: [ | ||
[ 'CHILD_SUBSCRIPT_COMPONENT', 'yy.ast.set({ scope: "child" })' ], | ||
[ 'DESCENDANT_SUBSCRIPT_COMPONENT', 'yy.ast.set({ scope: "descendant" })' ] ], | ||
SUBSCRIPT_COMPONENT: [ | ||
[ 'CHILD_SUBSCRIPT_COMPONENT', 'yy.ast.set({ scope: "child" })' ], | ||
[ 'DESCENDANT_SUBSCRIPT_COMPONENT', 'yy.ast.set({ scope: "descendant" })' ] ], | ||
CHILD_SUBSCRIPT_COMPONENT: [ | ||
[ '[ SUBSCRIPT ]', '' ] ], | ||
CHILD_SUBSCRIPT_COMPONENT: [ | ||
[ '[ SUBSCRIPT ]', '' ] ], | ||
DESCENDANT_SUBSCRIPT_COMPONENT: [ | ||
[ 'DOT_DOT [ SUBSCRIPT ]', '' ] ], | ||
DESCENDANT_SUBSCRIPT_COMPONENT: [ | ||
[ 'DOT_DOT [ SUBSCRIPT ]', '' ] ], | ||
SUBSCRIPT: [ | ||
[ 'SUBSCRIPT_EXPRESSION', '' ], | ||
[ 'SUBSCRIPT_EXPRESSION_LIST', '' ] ], | ||
SUBSCRIPT: [ | ||
[ 'SUBSCRIPT_EXPRESSION', '' ], | ||
[ 'SUBSCRIPT_EXPRESSION_LIST', '$1.length > 1? yy.ast.set({ expression: { type: "union", value: $1 } }) : $$ = $1' ] ], | ||
SUBSCRIPT_EXPRESSION_LIST: [ | ||
[ 'SUBSCRIPT_EXPRESSION , SUBSCRIPT_EXPRESSION', 'yy.ast.set({ expression: { type: "union", value: [ $1, $3 ] } })' ], | ||
[ 'SUBSCRIPT_EXPRESSION_LIST , SUBSCRIPT_EXPRESSION', 'yy.ast.node().expression.value.push( $3 )' ] ], | ||
SUBSCRIPT_EXPRESSION_LIST: [ | ||
[ 'SUBSCRIPT_EXPRESSION_LISTABLE', '$$ = [$1]'], | ||
[ 'SUBSCRIPT_EXPRESSION_LIST , SUBSCRIPT_EXPRESSION_LISTABLE', '$$ = $1.concat($3)' ] ], | ||
SUBSCRIPT_EXPRESSION: [ | ||
[ 'INTEGER', '$$ = { expression: { type: "numeric_literal", value: parseInt($1) } }; yy.ast.set($$)' ], | ||
[ 'ARRAY_SLICE', '$$ = { expression: { type: "slice", value: $1 } }; yy.ast.set($$)' ], | ||
[ 'STAR', '$$ = { expression: { type: "wildcard", value: $1 } }; yy.ast.set($$)' ], | ||
[ 'SCRIPT_EXPRESSION', '$$ = { expression: { type: "script_expression", value: $1 } }; yy.ast.set($$)' ], | ||
[ 'STRING_LITERAL', '$$ = { expression: { type: "string_literal", value: $1 } }; yy.ast.set($$)' ], | ||
[ 'FILTER_EXPRESSION', '$$ = { expression: { type: "filter_expression", value: $1 } }; yy.ast.set($$)' ] ], | ||
SUBSCRIPT_EXPRESSION_LISTABLE: [ | ||
[ 'INTEGER', '$$ = { expression: { type: "numeric_literal", value: parseInt($1) } }; yy.ast.set($$)' ], | ||
[ 'STRING_LITERAL', '$$ = { expression: { type: "string_literal", value: $1 } }; yy.ast.set($$)' ], | ||
[ 'ARRAY_SLICE', '$$ = { expression: { type: "slice", value: $1 } }; yy.ast.set($$)' ] ], | ||
STRING_LITERAL: [ | ||
[ 'QQ_STRING', "$$ = $1" ], | ||
[ 'Q_STRING', "$$ = $1" ] | ||
] | ||
SUBSCRIPT_EXPRESSION: [ | ||
[ 'STAR', '$$ = { expression: { type: "wildcard", value: $1 } }; yy.ast.set($$)' ], | ||
[ 'SCRIPT_EXPRESSION', '$$ = { expression: { type: "script_expression", value: $1 } }; yy.ast.set($$)' ], | ||
[ 'FILTER_EXPRESSION', '$$ = { expression: { type: "filter_expression", value: $1 } }; yy.ast.set($$)' ] ], | ||
STRING_LITERAL: [ | ||
[ 'QQ_STRING', "$$ = $1" ], | ||
[ 'Q_STRING', "$$ = $1" ] ] | ||
} | ||
@@ -98,0 +102,0 @@ }; |
@@ -20,2 +20,10 @@ var assert = require('assert'); | ||
JSONPath.prototype._first = function(obj, path) { | ||
assert.ok(obj instanceof Object, "obj needs to be an object"); | ||
assert.ok(Array.isArray(path), "we need a path array"); | ||
return this.query(obj, this.stringify(path)).shift(); | ||
} | ||
JSONPath.prototype.parent = function(obj, string) { | ||
@@ -28,5 +36,3 @@ | ||
var key = node.path.pop(); /* jshint unused:false */ | ||
var parentPath = this.stringify(node.path); | ||
var parent = this.query(obj, parentPath).shift(); | ||
return parent; | ||
return this._first(obj, node.path); | ||
} | ||
@@ -57,5 +63,5 @@ | ||
var node = this.nodes(obj, string).shift(); | ||
if (arguments.length >= 3) { | ||
var node = this.nodes(obj, string).shift(); | ||
if (!node) return this._vivify(obj, string, value); | ||
var key = node.path.slice(-1).shift(); | ||
@@ -69,2 +75,25 @@ var parent = this.parent(obj, this.stringify(node.path)); | ||
JSONPath.prototype._vivify = function(obj, string, value) { | ||
var self = this; | ||
assert.ok(obj instanceof Object, "obj needs to be an object"); | ||
assert.ok(string, "we need a path"); | ||
var path = this.parser.parse(string) | ||
.map(function(component) { return component.expression.value }); | ||
var setValue = function(path, value) { | ||
var key = path.pop(); | ||
var node = self._first(obj, path); | ||
if (!node) { | ||
setValue(path.concat(), typeof key === 'string' ? {} : []); | ||
node = self._first(obj, path); | ||
} | ||
node[key] = value; | ||
} | ||
setValue(path, value); | ||
return this.query(obj, string)[0]; | ||
} | ||
JSONPath.prototype.query = function(obj, string) { | ||
@@ -71,0 +100,0 @@ |
@@ -6,3 +6,3 @@ module.exports = function(arr, start, end, step) { | ||
if (step === 0) throw new Error("step cannot be zero"); | ||
step = step || 1; | ||
step = step ? integer(step) : 1; | ||
@@ -28,2 +28,3 @@ // normalize negative values | ||
for (var i = start; i != end; i += step) { | ||
if ((step < 0 && i <= end) || (step > 0 && i >= end)) break; | ||
result.push(arr[i]); | ||
@@ -30,0 +31,0 @@ } |
{ | ||
"name": "jsonpath", | ||
"description": "Query JavaScript objects with JSONPath expressions. Robust / safe JSONPath engine for Node.js.", | ||
"version": "0.1.3", | ||
"version": "0.1.4", | ||
"author": "david@fmail.co.uk", | ||
@@ -6,0 +6,0 @@ "scripts": { |
@@ -100,3 +100,3 @@ [![Build Status](https://travis-ci.org/dchester/jsonpath.png?branch=master)](https://travis-ci.org/dchester/jsonpath) | ||
`$..book[?(@.isbn)]` | Filter all books with isbn number | ||
`$..book[?(@.price<10)]` | Filter all books cheapier than 10 | ||
`$..book[?(@.price<10)]` | Filter all books cheaper than 10 | ||
`$..*` | All members of JSON structure | ||
@@ -103,0 +103,0 @@ |
@@ -168,2 +168,12 @@ var assert = require('assert'); | ||
test('union of three array slices', function() { | ||
var results = jp.query(data, "$.store.book[0:1,1:2,2:3]"); | ||
assert.deepEqual(results, data.store.book.slice(0,3)); | ||
}); | ||
test('slice with step > 1', function() { | ||
var results = jp.query(data, "$.store.book[0:4:2]"); | ||
assert.deepEqual(results, [ data.store.book[0], data.store.book[2]]); | ||
}); | ||
test('union of subscript string literal keys', function() { | ||
@@ -177,2 +187,57 @@ var results = jp.nodes(data, "$.store['book','bicycle']"); | ||
test('union of subscript string literal three keys', function() { | ||
var results = jp.nodes(data, "$.store.book[0]['title','author','price']"); | ||
assert.deepEqual(results, [ | ||
{ path: ['$', 'store', 'book', 0, 'title'], value: data.store.book[0].title }, | ||
{ path: ['$', 'store', 'book', 0, 'author'], value: data.store.book[0].author }, | ||
{ path: ['$', 'store', 'book', 0, 'price'], value: data.store.book[0].price } | ||
]); | ||
}); | ||
test('union of subscript integer three keys followed by member-child-identifier', function() { | ||
var results = jp.nodes(data, "$.store.book[1,2,3]['title']"); | ||
assert.deepEqual(results, [ | ||
{ path: ['$', 'store', 'book', 1, 'title'], value: data.store.book[1].title }, | ||
{ path: ['$', 'store', 'book', 2, 'title'], value: data.store.book[2].title }, | ||
{ path: ['$', 'store', 'book', 3, 'title'], value: data.store.book[3].title } | ||
]); | ||
}); | ||
test('union of subscript integer three keys followed by union of subscript string literal three keys', function() { | ||
var results = jp.nodes(data, "$.store.book[0,1,2,3]['title','author','price']"); | ||
assert.deepEqual(results, [ | ||
{ path: ['$', 'store', 'book', 0, 'title'], value: data.store.book[0].title }, | ||
{ path: ['$', 'store', 'book', 0, 'author'], value: data.store.book[0].author }, | ||
{ path: ['$', 'store', 'book', 0, 'price'], value: data.store.book[0].price }, | ||
{ path: ['$', 'store', 'book', 1, 'title'], value: data.store.book[1].title }, | ||
{ path: ['$', 'store', 'book', 1, 'author'], value: data.store.book[1].author }, | ||
{ path: ['$', 'store', 'book', 1, 'price'], value: data.store.book[1].price }, | ||
{ path: ['$', 'store', 'book', 2, 'title'], value: data.store.book[2].title }, | ||
{ path: ['$', 'store', 'book', 2, 'author'], value: data.store.book[2].author }, | ||
{ path: ['$', 'store', 'book', 2, 'price'], value: data.store.book[2].price }, | ||
{ path: ['$', 'store', 'book', 3, 'title'], value: data.store.book[3].title }, | ||
{ path: ['$', 'store', 'book', 3, 'author'], value: data.store.book[3].author }, | ||
{ path: ['$', 'store', 'book', 3, 'price'], value: data.store.book[3].price } | ||
]); | ||
}); | ||
test('union of subscript 4 array slices followed by union of subscript string literal three keys', function() { | ||
var results = jp.nodes(data, "$.store.book[0:1,1:2,2:3,3:4]['title','author','price']"); | ||
assert.deepEqual(results, [ | ||
{ path: ['$', 'store', 'book', 0, 'title'], value: data.store.book[0].title }, | ||
{ path: ['$', 'store', 'book', 0, 'author'], value: data.store.book[0].author }, | ||
{ path: ['$', 'store', 'book', 0, 'price'], value: data.store.book[0].price }, | ||
{ path: ['$', 'store', 'book', 1, 'title'], value: data.store.book[1].title }, | ||
{ path: ['$', 'store', 'book', 1, 'author'], value: data.store.book[1].author }, | ||
{ path: ['$', 'store', 'book', 1, 'price'], value: data.store.book[1].price }, | ||
{ path: ['$', 'store', 'book', 2, 'title'], value: data.store.book[2].title }, | ||
{ path: ['$', 'store', 'book', 2, 'author'], value: data.store.book[2].author }, | ||
{ path: ['$', 'store', 'book', 2, 'price'], value: data.store.book[2].price }, | ||
{ path: ['$', 'store', 'book', 3, 'title'], value: data.store.book[3].title }, | ||
{ path: ['$', 'store', 'book', 3, 'author'], value: data.store.book[3].author }, | ||
{ path: ['$', 'store', 'book', 3, 'price'], value: data.store.book[3].price } | ||
]); | ||
}); | ||
test('nested parentheses eval', function() { | ||
@@ -184,2 +249,13 @@ var pathExpression = '$..book[?( @.price && (@.price + 20 || false) )]' | ||
test('array indexes from 0 to 100', function() { | ||
var data = []; | ||
for (var i = 0; i <= 100; ++i) | ||
data[i] = Math.random(); | ||
for (var i = 0; i <= 100; ++i) { | ||
var results = jp.query(data, '$[' + i.toString() + ']'); | ||
assert.deepEqual(results, [data[i]]); | ||
} | ||
}); | ||
test('descendant subscript numeric literal', function() { | ||
@@ -186,0 +262,0 @@ var data = [ 0, [ 1, 2, 3 ], [ 4, 5, 6 ] ]; |
@@ -33,2 +33,27 @@ var assert = require('assert'); | ||
test('value method sets new key and value', function() { | ||
var data = {}; | ||
var a = jp.value(data, '$.a', 1); | ||
var c = jp.value(data, '$.b.c', 2); | ||
assert.equal(a, 1); | ||
assert.equal(data.a, 1); | ||
assert.equal(c, 2); | ||
assert.equal(data.b.c, 2); | ||
}); | ||
test('value method sets new array value', function() { | ||
var data = {}; | ||
var v1 = jp.value(data, '$.a.d[0]', 4); | ||
var v2 = jp.value(data, '$.a.d[1]', 5); | ||
assert.equal(v1, 4); | ||
assert.equal(v2, 5); | ||
assert.deepEqual(data.a.d, [4, 5]); | ||
}); | ||
test('value method sets non-literal key', function() { | ||
var data = { "list": [ { "index": 0, "value": "default" }, { "index": 1, "value": "default" } ] }; | ||
jp.value(data, '$.list[?(@.index == 1)].value', "test"); | ||
assert.equal(data.list[1].value, "test"); | ||
}); | ||
}); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
58138
25
1090