JSON API实现 | 格式化JSON String

4,059 阅读3分钟

抢我饭碗的原生JSON方法

最近沉迷正则,在刚刚完成了正则实现 | 格式化JSON String这篇使用正则手动对JSON字符串进行格式化的文章后,我收到了同事发来的“噩耗”,原来原生JSON方法是可以自动格式化JSON字符串的。不过也好在我刚刚知道这件事,让我可以在这之前自己尝试这个功能实现。

下面我将为大家带来原生JSON方法的妙用集合,后续也会继续研究网上其他人的手动格式化方法,对自己的方法进行对比与优化。

JSON对象

JSON对象包含两个方法: 用于解析 JavaScript Object Notation (JSON) 的 parse() 方法,以及将对象/值转换为 JSON字符串的 stringify() 方法。

除了这两个方法, JSON这个对象本身并没有其他作用,也不能被调用或者作为构造函数调用。

—— MDN

JSON妙用一:JSON.stringify() 美化JSON

JSON.stringify(value[, replacer [, space]])

space | 可选

指定缩进用的空白字符串,用于美化输出(pretty-print);

  • space为数字:该数量的空格将被视为一缩进单位;上限为10。该值若小于1,则意味着没有空格;
  • (以下demo使用两个空格缩进)
JSON.stringify({"foo": 9},null,2)
/* 返回值
"{
  "a": 9
}"
*/
  • space为字符串:该字符串将被作为一缩进单位

(以下demo使用制表符缩进)

JSON.stringify({"foo": 9},null,'\t')
/* 返回值
"{
	"a": 9
}"
*/
  • space未提供或为null:无缩进;

(以下demo无缩进)

JSON.stringify({"foo": 9})
// 返回值"{"a":9}"

JSON妙用二:使用JSON方法,自动遍历处理JSON属性

JSON的遍历方法,可以用来对JSON属性做过滤,对特殊字段做处理,比如过滤内置属性、系统属性,如:去掉updateAt等系统字段。

let sysAttrs = ['updater', 'updateAt'];

function replacer(key, value) {
  if (sysAttrs.includes(value)) {
    return undefined;
  }
  return value;
}

let jsonString = JSON.parse(JSON.stringify(foo, replacer));

JSON.stringify(value[, replacer [, space]])

replacer | 可选

指定处理JSON键值的函数(或其他),用来自动遍历JSON并处理。使该方法返回一个键值处理后的字符串。

JSON.parse(text[, reviver])

reviver | 可选

指定处理JSON键值的函数(或其他),用来自动遍历JSON并处理。使该方法返回一个键值处理后的对象。

——以上两个方法中第二个参数,异曲同工对JSON的键值进行了深度遍历处理,区别仅在于JSON.parse的第二个参数只支持回调函数,而JSON.stringify的第二个参数还支持数组。以及,JSON.parse是从最内层JSON向外遍历,而JSON.stringify从最外层JSON向内遍历。

以下就以JSON.stringify为例进行demo解读:

  • replacer为函数:该函数从外向内遍历JSON键值,并且首次参数为空字符串和要被stringify的对象,随后依次传入从外至内的键和值。函数内this指向当前遍历的键值对对象,参数有两个,分别是key、value,该函数返回JSON字符串中的value;若value返回为undefined,则该属性不会在返回值中输出。

(以下demo只输出值不为字符串的属性)

function replacer(key, value) {
  if (typeof value === "string") {
    return undefined;
  }
  return value;
}

var foo = {foundation: "Mozilla", model: "box", week: 45, transport: "car", month: 7};
var jsonString = JSON.stringify(foo, replacer);
// "{"week":45,"month":7}"
  • replacer为数组:如果 replacer 是一个数组,数组的值代表将被序列化成 JSON 字符串的属性名。

(以下demo只保留数组中的属性)

JSON.stringify(foo, ['week', 'month']);  
// '{"week":45,"month":7}', 只保留 “week” 和 “month” 属性值。

注意:被stringify的对象,若包含toJSON方法,该对象不会被直接序列化,而是调用 toJSON 方法后的返回值会被序列化。

var obj = {
  foo: 'foo'
};

var obj2 = {
  foo: 'foo',
  toJSON: function () {
    return 'bar';
  }
};

function replacer(key, value) {
    if(key === 'foo') return 'bang!';
    else return value;
}

JSON.stringify(obj, replacer);      // "{"x":{"foo":"bang!"}}"
JSON.stringify(obj2, replacer);      // "{"x":"bar"}"

JSON其他妙用

  1. 判断对象是否相等:JSON.stringify(a) === JSON.stringify(b); //true
  2. 判断对象是否包含:JSON.stringify(father).indexOf(JSON.stringify(son)) !== -1;//true
  3. 实现深拷贝:let obj2 = JSON.parse(JSON.stringify(obj))
  4. 实现localStorage/sessionStorage存对象:
window.localStorage.setItem(key, JSON.stringify(value)); // 存
let value = JSON.parse(window.localStorage.getItem(key)); // 取