Skip to content

Instantly share code, notes, and snippets.

@emilbayes
Created March 10, 2015 14:57
Show Gist options
  • Save emilbayes/e6b740529147a72205f0 to your computer and use it in GitHub Desktop.
Save emilbayes/e6b740529147a72205f0 to your computer and use it in GitHub Desktop.
Minimalistic JSON Pointer (RFC 6901) implementation. Does not support URI Fragments, but otherwise compliant
'use strict';
exports.get = function(document, pointer) {
//Empty pointer references the whole document
if(pointer === '') return document;
//Split the pointer into reference tokens and unescape
var referenceTokens = pointer.slice(1).split('/').map(unescape);
//Decent down the object iteratively
return referenceTokens.reduce(function(object, token) {
//Strip leading zeros from array indicies
if(Array.isArray(object)) token = parseInt(token);
//Throw an error on undefined values.
//In the case of '-' for an array index, this will be `NaN` due to the last
//line and should index an undefined value
if(object[token] === undefined) throw Error('Pointer is referencing non-existing value');
return object[token];
}, document);
};
function unescape(token) {
//Unescape as per Section 4, paragraph 2
return token.replace('~1', '/').replace('~0', '~');
}
exports = exports.get;
'use strict';
var test = require('tape');
var jsonPointer = require('../../../lib/json-pointer');
test('example', function(t) {
var json = {
foo: ['bar', 'baz'],
'': 0,
'a/b': 1,
'c%d': 2,
'e^f': 3,
'g|h': 4,
'i\\j': 5,
"k\"l": 6, // eslint-disable-line quotes
' ': 7,
'm~n': 8
};
var find = jsonPointer.get.bind(null, json);
t.same(find(''), json, 'allow empty pointer (return complete document)');
t.same(find('/foo'), ['bar', 'baz'], 'return the exact array');
t.is(find('/foo/0'), 'bar', 'return array at index');
t.is(find('/foo/01'), 'baz', 'strip leading zeros from indicies');
t.throws(find.bind(null, '/foo/-'), Error, 'throw on the special "array end" operator');
t.throws(find.bind(null, '/qux'), Error, 'throw on non-existing keys');
t.is(find('/'), 0, 'allow pointer to empty name');
t.is(find('/a~1b'), 1, 'escaped /');
t.is(find('/c%d'), 2, 'special char %');
t.is(find('/e^f'), 3, 'special char ^');
t.is(find('/g|h'), 4, 'special char |');
t.is(find('/i\\j'), 5, 'special char \\');
t.is(find("/k\"l"), 6, 'special char "'); // eslint-disable-line quotes
t.is(find('/ '), 7, 'special char ⎵ (space)');
t.is(find('/m~0n'), 8, 'escaped ~');
t.end();
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment