function readJSON( file, options, clbk ) {
	var opts;
	var done;
	if ( arguments.length < 3 ) {
		opts = {};
		done = options;
	} else {
		if ( isString( options ) ) {
			opts = {
				'encoding': options
			};
		} else {
			if ( !isObject( options ) ) {
				throw new TypeError( format( 'invalid argument. Options argument must be either a string or an object. Value: `%s`.', options ) );
			}
			opts = options;
		}
		done = clbk;
	}
	if ( !isFunction( done ) ) {
		throw new TypeError( format( 'invalid argument. Callback argument must be a function. Value: `%s`.', done ) );
	}
	readFile( file, opts, onRead );

	/**
	* Callback invoked upon reading a file.
	*
	* @private
	* @param {(Error|null)} error - error object
	* @param {(Buffer|string)} file - file contents
	* @returns {void}
	*/
	function onRead( error, file ) {
		if ( error ) {
			return done( error );
		}
		file = file.toString();
		if ( opts.encoding === 'utf8' ) {
			file = removeBOM( file );
		}
		if ( opts.reviver ) {
			file = parseJSON( file, opts.reviver );
		} else {
			file = parseJSON( file );
		}
		if ( instanceOf( file, Error ) ) {
			return done( file );
		}
		done( null, file );
	}
}
Asynchronously reads a file as JSON.

@param {(string|Buffer|integer)} file - file path or file descriptor
@param {(Options|string)} [options] - options
@param {(string|null)} [options.encoding] - file encoding
@param {string} [options.flag] - file status flag
@param {Function} [options.reviver] - JSON reviver
@param {Callback} clbk - callback
@throws {TypeError} options argument must be either a string or an object
@throws {TypeError} callback argument must be a function

@example
var resolve = require( 'path' ).resolve;

readJSON( resolve( __dirname, '..', 'package.json' ), onJSON );

function onJSON( error, data ) {
    if ( error ) {
        throw error;
    }
    console.dir( data );
}