jpath.js
function jptr(obj, prop, newValue) {
    //property not found
    if (typeof obj === 'undefined') return false;
	if ((!prop) || (prop == '#')) return obj;

	if (prop.startsWith('#')) prop = prop.slice(1);
	if (prop.startsWith('/')) prop = prop.slice(1);
	var props = prop.split('/');

	var current = props[0];
	current = current.replaceAll('~1','/');
	current = current.replaceAll('~0','~');

	var index = -1;
	if ((props.length>1) && (Array.isArray(obj[current]))) {
		var next = props[1];
		var value = parseInt(next,10);
		if (next == '-') {
			index = obj[current].length;
		}
		else {
			if (!isNaN(value)) index = value;
		}
		if (index>=0) {
			props.splice(1,1);
			prop = props.join('/');
		}
	}

    //property split found; recursive call
    if (props.length>1) {
		var pos = prop.indexOf('/');
        //get object at property (before split), pass on remainder
		if (index>=0) {
			return jptr(obj[current][index], prop.substr(pos+1),newValue); //was props
		}
		else {
			return jptr(obj[current], prop.substr(pos+1),newValue);
		}
	}
	//no split; get property[index] or property
	var source = obj;
	if (current) source = obj[current];
	if (index>=0) {
		if (index>=source.length) {
			if (typeof newValue != 'undefined') {
				source.push(newValue);
				return newValue;
			}
			else {
				return null;
			}
		}
		else {
			if (typeof newValue != 'undefined') {
				source[index] = newValue;
			}
			return source[index];
		}
	}
    else {
		if (typeof newValue != 'undefined') {
			obj[prop] = newValue;
			source = obj[prop];
		}
		return source;
	}
}
function jptr(obj, prop, newValue) {
    //property not found
    if (typeof obj === 'undefined') return false;
	if ((!prop) || (prop == '#')) return obj;

	if (prop.startsWith('#')) prop = prop.slice(1);
	if (prop.startsWith('/')) prop = prop.slice(1);
	var props = prop.split('/');

	var current = props[0];
	current = current.replaceAll('~1','/');
	current = current.replaceAll('~0','~');

	var index = -1;
	if ((props.length>1) && (Array.isArray(obj[current]))) {
		var next = props[1];
		var value = parseInt(next,10);
		if (next == '-') {
			index = obj[current].length;
		}
		else {
			if (!isNaN(value)) index = value;
		}
		if (index>=0) {
			props.splice(1,1);
			prop = props.join('/');
		}
	}

    //property split found; recursive call
    if (props.length>1) {
		var pos = prop.indexOf('/');
        //get object at property (before split), pass on remainder
		if (index>=0) {
			return jptr(obj[current][index], prop.substr(pos+1),newValue); //was props
		}
		else {
			return jptr(obj[current], prop.substr(pos+1),newValue);
		}
	}
	//no split; get property[index] or property
	var source = obj;
	if (current) source = obj[current];
	if (index>=0) {
		if (index>=source.length) {
			if (typeof newValue != 'undefined') {
				source.push(newValue);
				return newValue;
			}
			else {
				return null;
			}
		}
		else {
			if (typeof newValue != 'undefined') {
				source[index] = newValue;
			}
			return source[index];
		}
	}
    else {
		if (typeof newValue != 'undefined') {
			obj[prop] = newValue;
			source = obj[prop];
		}
		return source;
	}
}
JSON Pointer specification: http://tools.ietf.org/html/rfc6901