前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >将JSON对象格式化输出(上篇)

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

作者头像
用户3579639
发布2018-10-19 14:23:55
1.9K0
发布2018-10-19 14:23:55
举报

UPDATE:经公子大大提醒,使用JSON API就可以做到下面的效果。

请输入图片描述
请输入图片描述

(这后面的内容不用看了) 最近在使用Node.js开发项目,由于JavaScript内置了对JSON的支持,自然而然想到了使用JSON编写配置文件。

// app.json
{"mode": "prod", "log_path": "/data"}; //还有更多内容
var app = require('./app.json');
var fs = require('fs');
// 某些操作,保存app
fs.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;
    });
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档