Wenzi

JSON stringify 的一些不常见使用

蚊子前端博客
发布于 2024/04/22 10:21
介绍JSON stringify()几个不太常用但很有用的用法

JSON.stringify() 可以把 json 或 object 类型的数据转为 json string,但还有一些其他的使用场景。

官方地址: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify 。

1. 普通的转换 #

常见的操作是将 json 或 object 类型的数据转为 json string。

const user = {
  name: "小茶馆",
  score: 89,
};
JSON.stringify(user); // '{"name":"小茶馆","score":89}'

在转换过程中有个规则:若值为 undefined, Symbol, Function 等类型,该字段则不会被转换;

JSON stringify不转换某些类型

有的同学喜欢用 JSON.parse(JSON.stringify(obj)) 来进行深拷贝,若是一些数字、字符串之类的,确实没啥问题。但若有上面的几种类型,在转换后,字段就丢失了。

2. 第二个参数是数组或者函数 #

  1. 若是数组,则只转换数组中的 key,若是空数组,则不转换任何的 key;
  2. 若是函数,则每一项都会执行该回调函数:callback(key, value) => newValue 。

2.1 类型是数组 #

数组中的 key 只对对象类型的数据生效,若转换的格式是数组,则不起作用;

JSON.stringify({ name: "小茶馆", score: 89 }, ["name"]); // '{"name":"小茶馆"}'
JSON.stringify({ name: "小茶馆", score: 89 }, []); // '{}'
JSON.stringify(["a", "b", "c"], [1]); // '["a","b","c"]'

2.2 类型是函数 #

每一项数据都会执行该回调。结合上面不会转换 undefined 的规则,若不想要某个 key,则可以返回 undefined。 若其中某项的值为对象,则递归调用。

JSON.stringify({ name: "小茶馆", score: 89 }, (key, value) => {
  console.log(key, value); // name 小茶馆 , score 89
  return value;
}); // '{"name":"小茶馆","score":89}'

// 过滤掉值为number类型的字段
JSON.stringify({ name: "小茶馆", score: 89 }, (_, value) => {
  if (typeof value === "number") {
    return undefined;
  }
  return value;
}); // '{"name":"小茶馆"}'

3. 第三个参数 #

第 3 个参数用来控制字符串里面的间距,可以格式化展示所有的字段。参数既可以是数字,也可以是字符串。

? 是数字时,则表示每一级比上一级缩进几个空格(最多 10 个空格); ? 是字符串时,则以该字符串作为缩进字符(最多使用该字符串的前 10 个字符);

const obj = {
  name: "小茶馆",
  score: 89,
  tags: [
    { label: "足球", value: "football" },
    { label: "篮球", value: "basketball" },
  ],
};

console.log(JSON.stringify(obj, null, 2));
console.log(JSON.stringify(obj, null, "---"));

JSON stringify 格式化

在控制中只是输出对象时,很多时候他们的字段都是默认关闭的,需要手动一个个的点开。使用 JSON.stringify() 则可以默认展开所有的 key。

4. 将对象转为字符串比较 #

如有两个如下的对象实例:

const obj1 = { a: 1, b: 2, 1: "x" };
const obj2 = { b: 2, a: 1, 1: "x" };

使用 JSON.stringify() 转换这两个对象后的字符串是否相等?

JSON.stringify(obj1); // '{"1":"x","a":1,"b":2}'
JSON.stringify(obj2); // '{"1":"x","b":2,"a":1}'

发现输入的字符串是不一样的。而且 key1 还跑到了最前面。

这是为什么呢?这就涉及到 object 中 key 的顺序的问题。同理还有 Object.keys(obj) 输出的 key 的顺序。

这里有篇文章深入探究了 JavaScript 规范中关于对象的 key 的顺序的实现:Object.keys() 的顺序是如何定义的?

具体细节可以参看这篇文章,这里只说最后的结论:

  1. 纯数字的 key,且范围在[0~2^32-1]之间,升序排列后放在 keys 列表的最前面;若 key 不在该范围(负数或者更大的数),则作为字符串处理;
  2. 若 key 是字符串,按照定义时间顺序升序排列后添加到 keys 列表;即先定义的 key 在前,后定义的 key 在后;

在明确 key 的顺序后,就能知道转换后的字符串是否相等了。

标签:json
阅读(301)
Simple Empty
No data