lib/json-dry.js
function parse(object, reviver) {

	var undry_paths = new Map(),
	    retrieve    = {},
	    reviver,
	    result,
	    holder,
	    entry,
	    temp,
	    seen,
	    path,
	    key,
	    old = {};

	// Create the reviver function
	reviver = generateReviver(reviver, undry_paths);

	if (typeof object == 'string') {
		object = JSON.parse(object);
	}

	if (!object || typeof object != 'object') {
		return object;
	}

	result = walk(object, reviver);

	if (result == null) {
		return result;
	}

	// To remember which objects have already been revived
	seen = new WeakMap();

	// Maybe paths need another round of undrying
	undry_paths.extra_pass = [];

	// Iterate over all the values that require some kind of function to be revived
	undry_paths.forEach(function eachEntry(entry, path) {

		var path_array = entry.drypath,
		    path_string = path_array.join('.');

		// Regenerate this replacement wrapper first
		regenerate(result, null, entry, seen, retrieve, undry_paths, old, path_array.slice(0));

		if (entry.unDryConstructor) {
			entry.undried = entry.unDryConstructor.unDry(entry.value, false);
		} else if (entry.unDryFunction) {
			entry.undried = entry.unDryFunction(entry, null, entry.value);
		} else {
			entry.undried = entry.value;
		}

		// Remember the old wrapper entry, some other references
		// may still point to it's children
		old[path_string] = entry;

		if (entry.drypath && entry.drypath.length) {
			setPath(result, entry.drypath, entry.undried);
		}
	});

	for (var i = 0; i < undry_paths.extra_pass.length; i++) {
		entry = undry_paths.extra_pass[i];
		holder = entry[0];
		temp = entry[1];
		path = entry[2];

		for (key in holder) {
			if (holder[key] == temp) {
				holder[key] = temp.undried;
				break;
			}
		}

		path.pop();

		// Annoying workaround for some circular references
		if (path.length && path[path.length - 1] == 'value') {
			path.pop();
		}

		if (path.length) {

			// Get the other holder
			holder = retrieveFromPath(result, path);

			// If the holder object was not found in the result,
			// it was probably a child of ANOTHER holder that has already been undried & replaces
			// Just get the value from the object containing old references
			if (!holder) {
				holder = getFromOld(old, path);
			}

			for (key in holder) {
				if (holder[key] == temp) {
					holder[key] = temp.undried;
					break;
				}
			}
		}
	}

	// Only now we can resolve paths
	result = regenerate(result, result, result, seen, retrieve, undry_paths, old, []);

	if (result.undried != null && result.dry) {
		return result.undried;
	}

	return result;
}
function parse(object, reviver) {

	var undry_paths = new Map(),
	    retrieve    = {},
	    reviver,
	    result,
	    holder,
	    entry,
	    temp,
	    seen,
	    path,
	    key,
	    old = {};

	// Create the reviver function
	reviver = generateReviver(reviver, undry_paths);

	if (typeof object == 'string') {
		object = JSON.parse(object);
	}

	if (!object || typeof object != 'object') {
		return object;
	}

	result = walk(object, reviver);

	if (result == null) {
		return result;
	}

	// To remember which objects have already been revived
	seen = new WeakMap();

	// Maybe paths need another round of undrying
	undry_paths.extra_pass = [];

	// Iterate over all the values that require some kind of function to be revived
	undry_paths.forEach(function eachEntry(entry, path) {

		var path_array = entry.drypath,
		    path_string = path_array.join('.');

		// Regenerate this replacement wrapper first
		regenerate(result, null, entry, seen, retrieve, undry_paths, old, path_array.slice(0));

		if (entry.unDryConstructor) {
			entry.undried = entry.unDryConstructor.unDry(entry.value, false);
		} else if (entry.unDryFunction) {
			entry.undried = entry.unDryFunction(entry, null, entry.value);
		} else {
			entry.undried = entry.value;
		}

		// Remember the old wrapper entry, some other references
		// may still point to it's children
		old[path_string] = entry;

		if (entry.drypath && entry.drypath.length) {
			setPath(result, entry.drypath, entry.undried);
		}
	});

	for (var i = 0; i < undry_paths.extra_pass.length; i++) {
		entry = undry_paths.extra_pass[i];
		holder = entry[0];
		temp = entry[1];
		path = entry[2];

		for (key in holder) {
			if (holder[key] == temp) {
				holder[key] = temp.undried;
				break;
			}
		}

		path.pop();

		// Annoying workaround for some circular references
		if (path.length && path[path.length - 1] == 'value') {
			path.pop();
		}

		if (path.length) {

			// Get the other holder
			holder = retrieveFromPath(result, path);

			// If the holder object was not found in the result,
			// it was probably a child of ANOTHER holder that has already been undried & replaces
			// Just get the value from the object containing old references
			if (!holder) {
				holder = getFromOld(old, path);
			}

			for (key in holder) {
				if (holder[key] == temp) {
					holder[key] = temp.undried;
					break;
				}
			}
		}
	}

	// Only now we can resolve paths
	result = regenerate(result, result, result, seen, retrieve, undry_paths, old, []);

	if (result.undried != null && result.dry) {
		return result.undried;
	}

	return result;
}
function parse ( object , reviver ) { var undry_paths = new Map ( ) , retrieve = { } , reviver , result , holder , entry , temp , seen , path , key , old = { } ; // Create the reviver function reviver = generateReviver ( reviver , undry_paths ) ; if ( typeof object == 'string' ) { object = JSON . parse ( object ) ; } if ( ! object || typeof object != 'object' ) { return object ; } result = walk ( object , reviver ) ; if ( result == null ) { return result ; } // To remember which objects have already been revived seen = new WeakMap ( ) ; // Maybe paths need another round of undrying undry_paths . extra_pass = [ ] ; // Iterate over all the values that require some kind of function to be revived undry_paths . forEach ( function eachEntry ( entry , path ) { var path_array = entry . drypath , path_string = path_array . join ( '.' ) ; // Regenerate this replacement wrapper first regenerate ( result , null , entry , seen , retrieve , undry_paths , old , path_array . slice ( 0 ) ) ; if ( entry . unDryConstructor ) { entry . undried = entry . unDryConstructor . unDry ( entry . value , false ) ; } else if ( entry . unDryFunction ) { entry . undried = entry . unDryFunction ( entry , null , entry . value ) ; } else { entry . undried = entry . value ; } // Remember the old wrapper entry, some other references // may still point to it's children old [ path_string ] = entry ; if ( entry . drypath && entry . drypath . length ) { setPath ( result , entry . drypath , entry . undried ) ; } } ) ; for ( var i = 0 ; i < undry_paths . extra_pass . length ; i ++ ) { entry = undry_paths . extra_pass [ i ] ; holder = entry [ 0 ] ; temp = entry [ 1 ] ; path = entry [ 2 ] ; for ( key in holder ) { if ( holder [ key ] == temp ) { holder [ key ] = temp . undried ; break ; } } path . pop ( ) ; // Annoying workaround for some circular references if ( path . length && path [ path . length - 1 ] == 'value' ) { path . pop ( ) ; } if ( path . length ) { // Get the other holder holder = retrieveFromPath ( result , path ) ; // If the holder object was not found in the result, // it was probably a child of ANOTHER holder that has already been undried & replaces // Just get the value from the object containing old references if ( ! holder ) { holder = getFromOld ( old , path ) ; } for ( key in holder ) { if ( holder [ key ] == temp ) { holder [ key ] = temp . undried ; break ; } } } } // Only now we can resolve paths result = regenerate ( result , result , result , seen , retrieve , undry_paths , old , [ ] ) ; if ( result . undried != null && result . dry ) { return result . undried ; } return result ; }
Convert from a dried object

@author   Jelle De Loecker   <jelle@develry.be>
@since    1.0.0
@version  1.0.4

@param    {Object}   value

@return   {Object}
Convert from a dried object