将JSON对象格式化输出(上篇)

来源:互联网 发布:山中伸弥 知乎 编辑:程序博客网 时间:2024/06/15 13:30

UPDATE:经公子大大提醒,使用JSON API就可以做到下面的效果。
请输入图片描述
(这后面的内容不用看了)
最近在使用Node.js开发项目,由于JavaScript内置了对JSON的支持,自然而然想到了使用JSON编写配置文件。

// app.json{"mode": "prod", "log_path": "/data"}; //还有更多内容
var app = require('./app.json');var fs = require('fs');// 某些操作,保存appfs.writeFile('/path/to/app.json', JSON.stringify(app),    function(err) {        if(err) throw err;    });

如果配置文件比较复杂时,就需要分多行添加缩进等重新排版,但是只要程序读写保存过一次后,原来辛辛苦苦排版好的JSON文件内容又扎堆在一起了。对于开发人员来说或许不那么头疼,但对于运维人员(我司运维工程师们)却不是这样的,为了方便他们及我们读写修改JSON配置文件,于是就在网上搜索类json pretty tools的Node.js模块,便找到了prettyjson这个模块,不过这个模块时将对象输出成YAML风格,不太符合我的需求。
省略中间的过程。
修改后的代码:

'use strict';// ### Render function// *Parameters:*//// * **`data`**: Data to render// * **`options`**: Hash with different options to configure the parser// * **`indentation`**: Base indentation of the parsed output//// *Example of options hash:*////     {//       defaultIndentation: 2     // Indentation on nested objects//     }exports.render = function render(data, options, indentation) {  // Default values  indentation = indentation || 0;  options = options || {};  options.defaultIndentation = options.defaultIndentation || 2;  var output = [];  // Helper function to detect if an object can be directly serializable  var isSerializable = function(input, onlyPrimitives) {    if (typeof input === 'boolean' ||        typeof input === 'number' || input === null) {      return true;    }    if (typeof input === 'string' && input.indexOf('\n') === -1) {      return true;    }    return false;  };  var indentLines = function(string, spaces){    var lines = string.split('\n');    lines = lines.map(function(line){      return indent(spaces) + line;    });    return lines.join('\n');  };  var outputData = function(input) {    if (typeof input === 'string') {      // Print strings wraped by double quote      return '"' + input + '"';    }    if (input === true) {      return 'true';    }    if (input === false) {      return 'false';    }    if (input === null) {      return '';    }    if (typeof input === 'number') {      return input;    }    return input;  };  var removeLastComma = function(output) {      var lastElement = output[output.length-1];      output[output.length-1] = lastElement.substr(0, lastElement.length-1);  };  var indent = function(numSpaces) {    return new Array(numSpaces+1).join(' ');  };  // Render a string exactly equal  if (isSerializable(data)) {    output.push(indent(indentation) + outputData(data));  }  else if (typeof data === 'string') {    var lines = data.split('\n');    lines.map(function(line){      return indent(indentation + options.defaultIndentation) + '"' + line + '"';    });    output.push(lines.join(',\n'));  }  else if (Array.isArray(data)) {    var line = indent(indentation);    indentation = indentation + options.defaultIndentation;    output.push(line + '[');    // If the array is empty    if (data.length === 0) {      output.push(indent(indentation) +' ');    } else {      data.forEach(function(element) {        if(isSerializable(element)) {            output.push(indent(indentation) + outputData(element) + ',');        }else {            output.push(exports.render(element, options, indentation) + ',');        }      });      removeLastComma(output);    }    output.push(line + '],');  }  else if (typeof data === 'object') {    var line = indent(indentation);    output.push(line+'{');    var key;    var isError = data instanceof Error;    indentation = indentation + options.defaultIndentation;    Object.getOwnPropertyNames(data).forEach(function(i) {      // Prepend the index at the beginning of the line      key = ('"' + i +'"'+ ': ');      key = indent(indentation) + key;      // Skip `undefined`, it's not a valid JSON value.      if (data[i] === undefined) {        return;      }      if(isSerializable(data[i])) {        output.push(key + outputData(data[i]) + ',');      }else {        var temp = exports.render(data[i], options, indentation);        output.push(key + temp.trim() + ',');      }    });    removeLastComma(output);    output.push(line + '},');  }  removeLastComma(output);  // Return all the lines as a string  return output.join('\n');};// ### Render from string function// *Parameters:*//// * **`data`**: Data to render as a string// * **`options`**: Hash with different options to configure the parser// * **`indentation`**: Base indentation of the parsed output//// *Example of options hash:*////     {//       defaultIndentation: 2     // Indentation on nested objects//     }exports.renderString = function renderString(data, options, indentation) {  var output = '';  var parsedData;  // If the input is not a string or if it's empty, just return an empty string  if (typeof data !== 'string' || data === '') {    return '';  }  // Remove non-JSON characters from the beginning string  if (data[0] !== '{' && data[0] !== '[') {    var beginingOfJson;    if (data.indexOf('{') === -1) {      beginingOfJson = data.indexOf('[');    } else if (data.indexOf('[') === -1) {      beginingOfJson = data.indexOf('{');    } else if (data.indexOf('{') < data.indexOf('[')) {      beginingOfJson = data.indexOf('{');    } else {      beginingOfJson = data.indexOf('[');    }    output += data.substr(0, beginingOfJson) + '\n';    data = data.substr(beginingOfJson);  }  try {    parsedData = JSON.parse(data);  } catch (e) {    // Return an error in case of an invalid JSON    return 'Error:' + ' Not valid JSON!';  }  // Call the real render() method  output += exports.render(parsedData, options, indentation);  return output;};

这样之后原来程序代码基本不变,在保存对象到JSON文件时做了调整:

+var prettyjson = require('./lib/prettyjson');-fs.writeFile('/path/to/app.json', JSON.stringify(app),+fs.writeFile('/path/to/app.json', prettyjson.render(app),    function(err) {        if(err) throw err;    });
0 0
原创粉丝点击