手写一个格式化json工具

2022-12-27 14:21:53 浏览数 (1)

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第3天,点击查看活动详情

是个前端就离不开JSON,之前一直使用各种站长工具,然后天天看广告,然后自己萌生了自己写JSON格式化工具的想法,于是自己撸了一个轮子。废话不多说,我们手写一个格式化json工具。。 干货从第四步开始,着急的同学直接看第三步,不影响阅读。

第一步,拿到JSON字符串

代码语言:javascript复制
  let stringJson = JSON.stringify({ editor: { editor: { editor: { editor: 'aa' } } } });

第二步,放到一个textarea里面方便编辑

代码语言:javascript复制
function Editor() {
  // fetch('/tripdocs/test/api', { method: 'POST' });
  // 这里写一个可以格式化的json


  let stringJson = JSON.stringify({ editor: { editor: { editor: { editor: 'aa' } } } });

  return <textarea className="editor" defaultValue={stringJson}></textarea>;
}

第三步,初步实现

代码语言:javascript复制
function Editor() {
  // fetch('/tripdocs/test/api', { method: 'POST' });
  // 这里写一个可以格式化的json


  let stringJson = JSON.stringify({ editor: { editor: { editor: { editor: 'aa' } } } });
  stringJson = stringJson.replace(/{/gi, '{n');
  stringJson = stringJson.replace(/}/gi, 'n}');
  return <textarea className="editor" defaultValue={stringJson}></textarea>;
}

效果图如下

第四步,优化显示——简单处理object,增加空格

这一步,说明一下,json其实是一个树形结构。需要按照深度优先进行遍历。每深入一层就需要多加2个空格。

这时候需要树形结构,所以我放弃了直接用正则,转而使用递归的方式。

直接上方法

首先需要一个方法打印空格,这里利用数组进行操作

代码语言:javascript复制
function printSpace(num: number) {
  return new Array(num).fill('    ').join('');
}

接下来,我们需要处理传入的对象,但是我不知道,他是否合法是否有循环引用

这里利用JSON携带的函数取巧处理

代码语言:javascript复制
function printJson(tObj: Object, i: number = 1) {
  const count = i || 1;
  // TODO 判断是不是纯净的object,这里先当纯净的处理 利用JSON parse
  const obj = JSON.parse(JSON.stringify(tObj));
}

这里我们一共会遇到三类情况,纯净的Object、数组、其他基础类型的值。

其他基础类型:Number、String、Boolean、object、Null ps:不包含 undefined、Symbol(),会被 JSON.stringify 过滤

伪代码

代码语言:javascript复制
  if (obj &amp;&amp; Array.isArray(obj)) {

  } else if (obj &amp;&amp; typeof obj === 'object') {

  } else {
  
  }

重要的步骤来了,深度遍历。这里先只考虑纯净的object和其他基础类型的值

代码语言:javascript复制
function printJson(tObj: Object, i: number = 0) {
  const count = i || 0;
  // TODO 判断是不是纯净的object,这里先当纯净的处理 利用JSON parse
  const obj = JSON.parse(JSON.stringify(tObj));
  if (obj &amp;&amp; Array.isArray(obj)) {

  } else if (obj &amp;&amp; typeof obj === 'object') {
    let str = '';
    // 遍历object
    Object.keys(obj).forEach(key => {
    // 换行 加空格 给key加双引号 递归处理子对象
      str  = 'n'   printSpace(count   1)   '"'   key   '"'   ' : '   printJson(obj[key], count   1);
      // 最后加,
      str  = ',';
    });
    // 首部{不加空格,尾部}加空格
    return `{${str}n${printSpace(count)}}`;
  } else {
  // string 类型加双引号
    if (typeof obj === 'string') {
      return '"'   obj   '"';
    }
    return obj;
  }
}
function printSpace(num: number) {
  return new Array(num).fill('    ').join('');
}

第五步,处理数组

数组最大的不同是,数组没有key

以下是完整代码

代码语言:javascript复制
function printJson(tObj: Object, i: number = 0) {
  const count = i || 0;
  // TODO 判断是不是纯净的object,这里先当纯净的处理 利用JSON parse
  const obj = JSON.parse(JSON.stringify(tObj));
  if (obj &amp;&amp; Array.isArray(obj)) {
    let str = '';
    Object.keys(obj).forEach(key => {
      str  = 'n'   printSpace(count   1)   printJson(obj[key], count   1);
      str  = ',';
    });
    return `[${str}n${printSpace(count)}]`;
  } else if (obj &amp;&amp; typeof obj === 'object') {
    let str = '';
    Object.keys(obj).forEach(key => {
      str  = 'n'   printSpace(count   1)   '"'   key   '"'   ' : '   printJson(obj[key], count   1);
      str  = ',';
    });
    return `{${str}n${printSpace(count)}}`;
  } else {
    if (typeof obj === 'string') {
      return '"'   obj   '"';
    }
    return obj;
  }
}
function printSpace(num: number) {
  return new Array(num).fill('    ').join('');
}
function Editor() {

  let stringJson = printJson({
    type: 'table',
    row: 5,
    column: 6,
    isShow: null,
    isDrag: undefined,
    isDrag2: Symbol('ss'),
    hwEach: [
      ['109px', '109px', '109px', '109px', '109px', '109px'],
      ['109px', '109px', '109px', '109px', '109px', '109px'],
    ],
  });
  //   stringJson = stringJson.replace(/{/gi, '{n');
  //   stringJson = stringJson.replace(/}/gi, 'n}');

  return (
    <textarea
      className="editor"
      defaultValue={stringJson}
      onContextMenu={e => {
        e.preventDefault();
      }}
    ></textarea>
  );
}

此时效果如下

0 人点赞