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;
	}
}
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
JSON Pointer specification : http : // tools . ietf . org / html / rfc6901