UNPKG

easyjson

Version:

An easy way to manipulate JSON file with add/delete/modify/get json data, support nested data.

348 lines (319 loc) 8.19 kB
/** * Module dependencies */ var fs = require('fs'); /** * Expose `EasyJSON`. */ exports = module.exports = new EasyJSON; /** * Object#toString() */ var toString = Object.prototype.toString; /** * Array#isArray shim */ var isArray = Array.isArray || function (arr) { return toString.call(arr) == '[object Array]'; } /** * isNumber shim */ var isNumber = function (n) { return !isNaN(parseFloat(n)) && isFinite(n); } /** * Initialize a new `EasyJSON`. * * @api public */ function EasyJSON() { if (!(this instanceof EasyJSON)) { return new EasyJSON; } } /** * Choose the JSON file at `jsonPath` * * @param {String} jsonPath * @return {EasyJSON} * @api public */ EasyJSON.prototype.path = function (jsonPath) { if (!~jsonPath.indexOf('.json')) { jsonPath += '.json'; } this.jsonPath = jsonPath; return this; } /** * Return the content of JSON * @return {[String]} */ EasyJSON.prototype.read = function () { return fs.readFileSync(this.jsonPath, 'utf8'); }; /** * Express the JSON * @return {EasyJSON} */ EasyJSON.prototype.express = function () { console.log(this.read()); return this; } /** * add datas to json file, support nested data * @param {[String]} str * @param {[Object]} value * @param {[Number]} index * @return{EasyJSON} [description] */ EasyJSON.prototype.add = function (str, value, index) { var chunk = this.read(), obj = JSON.parse(chunk), nest = this.getNested(str), pre = this.getPre(str)[0], ret, gene, exist; if (typeof this.get(str) === 'undefined') { if (nest.length === 0) { obj[str] = value; } else if (nest.length === 1) { if (typeof this.get(pre) === 'undefined') { isNumber(nest[0][0]) ? obj[pre] = [value] : (obj[pre] = {}, obj[pre][nest[0][0]] = value); } else { (isArray(this.get(pre))) ? obj[pre].splice(nest[0][0], 0, value) : obj[pre][nest[0][0]] = value; } } else { if (typeof this.get(pre) === 'undefined') { isNumber(nest[nest.length - 1][0]) ? ret = [value] : (ret = {}, ret[nest[nest.length - 1][0]] = value); for (var i = nest.length - 2; i >= 0; --i) { if (isNumber(nest[i][0])) { gene = []; gene.splice(nest[i][0], 0, ret); ret = gene; } else { gene = {}; gene[nest[i][0]] = ret; ret = gene; } } obj[pre] = ret; } else { for (var i = nest.length - 2; i >= 0; --i) { str = str.replace(/\[[a-zA-Z_$][a-zA-Z0-9_$]*\]$|\[0\]$|\[[1-9]+[0-9]*\]$/,'') if (typeof this.get(str) !== 'undefined') { exist = i; break; } else { continue; } } if (typeof exist === 'undefined') exist = -1; ret = value; for (var i = nest.length - 1; i > exist + 1; --i) { if (isNumber(nest[i][0])) { gene = []; gene.splice(nest[i][0], 0, ret); ret = gene; } else { gene = {}; gene[nest[i][0]] = ret; ret = gene; } } e_ret = this.get(str); if (typeof e_ret === 'undefined') { obj[pre][nest[0][0]] = ret; } else { isArray(e_ret) ? e_ret.splice(nest[exist + 1][0], 0, ret) : e_ret[nest[exist + 1][0]] = ret; for (var i = exist; i >= 0; --i) { // aaa[bbb][ccc] => aaa[bbb] str = str.replace(/\[[a-zA-Z_$][a-zA-Z0-9_$]*\]$|\[0\]$|\[[1-9]+[0-9]*\]$/,'') ret = this.get(str); ret[nest[i][0]] = e_ret; e_ret = ret; } obj[pre] = e_ret; } } } } else if (isArray(this.get(str))) { // push the value to array if (nest.length === 0) { (typeof index === 'undefined') ? obj[pre].push(value) : obj[pre].splice(index, 0, value); } else if (nest.length === 1) { parse = this.get(pre); (typeof index === 'undefined') ? parse[nest[0][0]].push(value) : parse[nest[0][0]].splice(index, 0, value); obj[pre] = parse; } else { str = str.replace(/\[[a-zA-Z_$][a-zA-Z0-9_$]*\]$|\[0\]$|\[[1-9]+[0-9]*\]$/,'') parse = this.get(str); (typeof index === 'undefined') ? parse[nest[nest.length - 1][0]].push(value) : parse[nest[nest.length - 1][0]].splice(index, 0, value); for (var i = nest.length - 2; i >= 0; --i) { str = str.replace(/\[[a-zA-Z_$][a-zA-Z0-9_$]*\]$|\[0\]$|\[[1-9]+[0-9]*\]$/,'') ret = this.get(str); ret[nest[i][0]] = parse; parse = ret; } obj[pre] = parse; } } else { console.log('key has already exist!') } this.write(obj); return this; } /** * Delete the specific JSON item,support nested data * @param {String} keyToDel * @return {EasyJSON} */ EasyJSON.prototype.del = function (str) { var chunk = this.read(), obj = JSON.parse(chunk), nest = this.getNested(str), pre = this.getPre(str)[0], ret; if (nest.length === 0) { obj = JSON.parse(chunk, function (key, val) { if (key === str) { return undefined; } return val; }); } else if (nest.length === 1) { parse = this.get(pre); if (isArray(parse)) { parse.splice(nest[0][0], 1); } else { delete parse[nest[0][0]] } obj[pre] = parse; } else { str = str.replace(/\[[a-zA-Z_$][a-zA-Z0-9_$]*\]$|\[0\]$|\[[1-9]+[0-9]*\]$/,'') parse = this.get(str); if (isArray(parse)) { parse.splice(nest[nest.length - 1][0], 1); } else { delete parse[nest[nest.length - 1][0]] } for (var i = nest.length - 2; i >= 0; --i) { str = str.replace(/\[[a-zA-Z_$][a-zA-Z0-9_$]*\]$|\[0\]$|\[[1-9]+[0-9]*\]$/,'') ret = this.get(str); ret[nest[i][0]] = parse; parse = ret; } obj[pre] = parse; } this.write(obj); return this; } /** * Modify the value of specific JSON item, support nested data * @param {String} keyToChange * @param {String} valToChange * @return {EasyJSON} */ EasyJSON.prototype.modify = function (str, value) { var chunk = this.read(), obj = JSON.parse(chunk), nest = this.getNested(str), pre = this.getPre(str)[0], ret; if (nest.length === 0) { obj = JSON.parse(chunk, function (key, val) { if (key === str) { return value; } return val; }); } else if (nest.length === 1) { parse = this.get(pre); parse[nest[0][0]] = value; obj[pre] = parse; } else { str = str.replace(/\[[a-zA-Z_$][a-zA-Z0-9_$]*\]$|\[0\]$|\[[1-9]+[0-9]*\]$/,'') parse = this.get(str); parse[nest[nest.length - 1][0]] = value for (var i = nest.length - 2; i >= 0; --i) { str = str.replace(/\[[a-zA-Z_$][a-zA-Z0-9_$]*\]$|\[0\]$|\[[1-9]+[0-9]*\]$/,'') ret = this.get(str); ret[nest[i][0]] = parse; parse = ret; } obj[pre] = parse; } this.write(obj); return this; } /** * Write the updated data to JSON file * @param {String} data * @return {EasyJSON} */ EasyJSON.prototype.write = function (data) { fs.writeFileSync(this.jsonPath, this.beauty(data)); return this; } /** * Get the value of specific JSON item * @param {String} str * @return {String} */ EasyJSON.prototype.get = function (str) { var chunk = this.read(), obj = JSON.parse(chunk); var nest = this.getNested(str); var pre = this.getPre(str)[0]; var ret; if (nest.length === 0) { return obj[str]; } else { ret = obj[pre]; for (var i = 0; i < nest.length; ++i) { if (typeof ret === 'undefined') { return undefined; } else if (i != nest.length - 1) { ret = ret[nest[i][0]]; } else { return ret[nest[i][0]]; } } } } /** * Format the JSON data * @param {Object} obj * @return {String} */ EasyJSON.prototype.beauty = function (obj) { return JSON.stringify(obj, null, 4) } /** * Get the nested data. aaa[bbb][ccc] => [['bbb',index:3,input:'aaa[bbb][ccc]'],['ccc',index:8,input:'aaa[bbb][ccc]']] * @param {[String]} str nested data * @return {[Array]} */ EasyJSON.prototype.getNested = function (str) { var reg = /\[[a-zA-Z_$][a-zA-Z0-9_$]*\]|0|[1-9]+[0-9]*/g; var brace = []; var ret; while ((ret = reg.exec(str)) !== null) { if (/\[/.test(ret[0])) { ret[0] = ret[0].substr(1, ret[0].length - 2); } brace.push(ret); } return brace; } /** * Get the prefix of nested data. aaa[bbb][ccc] => aaa * @param {[String]} str * @return {[Array]} */ EasyJSON.prototype.getPre = function (str) { var reg = /^[a-zA-Z_$][a-zA-Z0-9_$]*/; var ret = reg.exec(str); return ret; }