Recently my coworker (Gnuvince) gave me the nice idea of using a path based approach like xPath to get properties of JSON objects.
My first thought was to replicate xPath's syntax, but it quickly came apparent that beside of being way to heavy, it didn't fit at all.
On the other hand, jQuery's selector approach turned out to be the perfect syntax. I wrote a working and extensible prototype, which I <sarcasm>creatively</sarcasm> decided to name jPath (source code).
var employee: {
name: 'John Doe',
phone: '(555) 555-1234',
bookmarks: ['google.com', ...],
prefs: {
color: 'blue',
page: 'http://www.google.com/'
}
}
};
$(employee).jpath('name'); // John Doe
$(employee).jpath('bookmarks'); // ['google.com', 'reddit.com', 'xkcd.com']
$(employee).jpath('prefs.color'); // blue
I find it syntactically sexy. But more importantly, it takes cares of checking if the property is defined before returning it. Which means that when requesting an property of an undefined property it will consistently return false:
// plain javascript
alert(enployee.rights); // 'undefined'
alert(employee.rights.constitutional); // reference error exception
// leads to ugly and redundant code like this:
if (employee && employee.rights.constitutional && employee.rights.constitutional) { ... }
// jPath
$(employee).jpath('rights'); // false
$(employee).jpath('rights.constitutional'); // false
Until now it's all cute, but I though I could spice it up and add expressions to it, again like jQuery' selectors.
$(employee).jpath('name:match(John)'); // return true
$(employee).jpath('bookmarks:eq(2)'); // return 'xkcd.com'
$(employee).jpath('color:is(blue)'); // return true
| expr | description |
|---|---|
| :contains(value) | Returns true if the object's contains value |
| :first | Returns the first element of an object |
| :last | Returns the last element of an object |
| :eq(N) | Returns the Nth element of an array or the N property of an array |
| :is(str) | Returns true if the object's value == str |
| :match(str) | Returns true if the object's value match str |
It's quite easy to add custom expressions, here's two examples:
(function($){
$.extend(jpath.expr, { // s: scope, k: key, p: param
'eq': function(s, k, p) {
return s[k] && s[k][p] || false;
},
'first': function(s, k) {
return s[k] && s[k][0] || false;
}
});
})(jQuery);
Axis too are extensible. Until now I only considered the "." (dot) to access child property, but there's probably more I could do. So I let room for expansion here too.
(function($){
axis: { // scope, property
'.': function(s, k) {
return $.jpath.getObj(s, k);
}
}
})(jQuery);
It's an experimental plugin, I still haven't tested really it so use it on a production site at your own risks.
Feedbacks are more than welcome. If you have any improvements idea or suggestions, please don't hesitate.
Looking cute.. Going to test your plugin. Thank you!
permalink Blake ~ October 4, 2008 at 6:35 p.m.