JPath

XPath for JSON

JPath is a simple lightweight Javascript Class which provides an XPath-like querying ability to JSON objects.

Download JPath 1.0.5

Features

  • basic node selection
  • element index selection
  • unlimited, nested predicate selections via inline javascript functions
  • 2 methods of querying, chained javascript functions or traditional XPath query string
  • root, parent, global node selections
  • predicate functions [ last(), position(), count() ]
  • boolean operators

Using JPath

There are two syntactic methods to using JPath — chained method calls or an XPath query.

Chained method calls offers the most control but with a high level of complexity. XPath query is a lot easier to use but with the caveat that it’s considered beta and rather limited as far as Javascript features go.

Example JSON Object Used

var library = {
   'name' :'My Library',
   '@open' : '2007-17-7',
   'address' : {
	'city' : 'Springfield',
	'zip' : '12345',
	'state' : 'MI',
	'street' : 'Mockingbird Lane'
   },
   'books':[
	{
	'title' : 'Harry Potter',
	'isbn'  : '1234-1234',
	'category' : 'Childrens',
	'available' : '3',
	'chapters' : [ 'Chapter 1', 'Chapter 2' ]
	},
	{
	'title' : 'Brief History of time',
	'isbn'  : '1234-ABCD',
	'category' : 'Science',
	'chapters' : [ '1', '2' ]
	},
	{
	'title' : 'Lord of the Rings',
	'isbn'  : '1234-PPPP',
	'category' : 'Fiction',
	'chapters' : [ 'Section 1', 'Section 2' ]
        }
   ],
   'categories' : [
        {'name':'Childrens', 'description':'Childrens books'},
        {'name':'Science', 'description':'Books about science'},
        {'name':'Fiction', 'description':'Fiction books'}
   ]};

Chained Methods

For each node selection there is a built in method named $() used to find the node. Most JPath method calls returns another JPath object, which is why Chained Methods can be used.

var jp = new JPath( library);

//will result in "Springfield"
jp.$('address').$('city').json

//with simple node selects this can be
//condensed too
jp.$('address/city').json;

//will grab the "Brief History of time"
//book object
jp.$('books').$(1).json;

//will grab all the books/category
//properties
jp.$$('category').json;

//will grab all book objects that have
//a property of available > 0
jp.$('books').$(function(n){
   return( n.$('available').json );
}).json;

//this will do the same query but with
//less code
jp.$('books').f("$('available').json;").json;

XPath Query

This is a super-awesome-easy way of selecting objects within a JSON block. These are the exact equivalent queries as performed above.

var jp = new JPath( library);

//will result in "Springfield"
jp.query('address/city');

//will grab the "Brief History of time"
//book object
jp.query('books[1]');
//will grab all the books/category
//properties
jp.query('//category');

//will grab all book objects that have
//a property of available > 0
jp.query('/books[available]');

//a more advanced query showing how predicates can be nested//
//this will return 'Fiction Books'
jp.query("categories[name == /books[last()]/category ]/description");

API Documentation

(JPath) new JPath( object json [, JPath parent ] );

Creates a new JPath object embedded with the passed json object. The second parameter is used by internal functions to create an object trail when chaining the methods.

(object) JPath.json

This property holds the current json object we want to traverse.

(JPath) JPath.$( mixed name );

Main query method. This method can accept a string, number or function. Based on what is passed determines what action is taken.

String – Will look at the current json property for a property named name or, in the case the current object is an array, through an array of objects for all properties named name as a new JPath object.

Number – Will look at the current json property as an array and return the element found at name as a new JPath object.

Function – Will use the function as an iterator to use on every property found within the json object. The function must accept one parameter — a json object wrapped in a JPath object. The iterator must return a boolean true/false determining if the property in particular should be returned in the nodeset. As always, the result will be an array wrapped in a new JPath object.

(JPath) JPath.$$( mixed name );

Global query method. This method can accept a string, number or function. Based on what is passed determines what action is taken.

String – Will recursivly look at the current json property for a property named name or, in the case the current object is an array, through an array of objects for all properties named name as a new JPath object.

Number – Will recursivly look at the current json property as an array and return the element found at name as a new JPath object.

Function – Will recursivly use the function as an iterator to use on every property found within the json object. The function must accept one parameter — a json object wrapped in a JPath object. The iterator must return a boolean true/false determining if the property in particular should be returned in the nodeset. As always, the result will be an array wrapped in a new JPath object.

(JPath) JPath.f( mixed iterator );

This is an alternative way to use a function to select json nodes.

As a shortcut, this function will accept a string and treat it as the guts of an iterator.

Example:

f("position() > 1 && $('name').json != null")

will become

function(j){
   with(j){
      return( position() > 1 && $('name').json != null )
   }
}

(mixed) JPath.query( string path );

Perform an XPath like query. Currently supported XPath commands…

/tagname
//tagname
tagname
* wildcard
[] predicates
operators ( >=, ==, <= )
array selection
..
*
and, or
nodename[0]
nodename[last()]
nodename[position()]
nodename[last()-1]
nodename[somenode > 3]/node
nodename[count() > 3]/node

(JPath) JPath.root();

Returns a root JPath object, equivalent to “/” in XPath.

(JPath) JPath.parent();

Returns the parent json object wrapped in JPath. Equivalent to “..” in XPath.

(boolean) JPath.last();

Only available within a function iterator or the “[]” predicate, returns true if the currently processing node is the last.

(number) JPath.position();

Only available within a function iterator or the “[]” predicate, returns the index of the currently processing node.

(number) JPath.count( nodename );

Only available within a function iterator or the “[]” predicate, returns the number of the nodes named nodename.

(Array) JPath.findAllByRegExp( RegExp re, object obj )

Utility function for searching through an object using a regular expression. For internal use.

12 Responses to “JPath”

  1. roel Says:

    how do you query for example book item/record with isbn = ’1234-PPPP’?

    thanks

  2. JSON and xpath-like filtering « Ramblings Says:

    [...] JPath – bluelinecity.com [...]

  3. JSON (JavaScript Object Notation) « AMC RAHARJA Says:

    [...] JPath. [...]

  4. Usenet Says:

    We used this in the development of our website and thought it worked very well.

  5. Venkat Says:

    Is XPath Querying functionality still considered a beta ?

  6. Venkat Says:

    Could you help me with this ?

    http://stackoverflow.com/questions/11174712/is-this-a-valid-xpath-query/11174764#11174764

  7. benglish Says:

    Yes it’s still considered beta.

  8. Killer Says:

    Can I change value in json object by this class?
    Example:
    JPath.query(‘//ROOT/NODES/NODE’,'NEW VALUE’); #write new value
    JPath.query(‘//ROOT/NODES/NODE’); # return ‘NEW VALUE’

  9. benglish Says:

    Sorry JPath was built as just a querying library.

  10. mbielski Says:

    If there is a Google group for JPath I can’t find it, so I am posting my question here. I’m sure I am probably just missing it, but is there a means available to pass a variable into a query? Something like this, for example:

    var myVar = [{"button":{"text":"I am a Menu","image":"","itemcode":"","children":[{"button":{"text":"I am a Sub Menu","image":"","itemcode":"","children":[{"button":{"text":"I am a Sub Sub Item","image":"","itemcode":"","children":[]}}]}},{“button”:{“text”:”I am a Sub Item”,”image”:”",”itemcode”:”",”children”:[]}}]}},{“button”:{“text”:”I am an Item”,”image”:”",”itemcode”:”",”children”:[]}}];
    var searchTerm = “I am a Sub Menu”;
    var jp = new JPath(myVar );
    var SearchResult = jp.query(“//text == ‘” + searchTerm + “‘”);

    When I try this SearchResult is undefined. So, where am I missing the nuances of selecting?

  11. benglish Says:

    It uses a syntax similar to XPath. So for your question you’ll want to do something along the lines of this…

    var SearchResult = jp.query(“//button[text == '"+ searchTerm +"']“);

  12. martin Says:

    Another great addition to my JSON tool kit. Thank you. I can use this to help sift through some geographic mapping data.

Leave a Reply





  • I Killed WarMECH

    Morgue File

    Electronic Frontier Foundation

    Librarian Chick, a collection of links to the best of the Internet's FREE resources for those with big brains and small pocketbooks!



    Flying Spaghetti Monster

    The Out Campaign: Scarlet Letter of Atheism