JSON.stringify的隐藏用法

关于JSON.stringify()最常见的用法,应该通过JSON.parse(JSON.stringify())来做对象的拷贝,但是关于JSON.stringify()实际还有很多用法。在开始之前,先来看一段简单的代码:

javascript 复制代码
JSON.stringify({
"reqId": "f67271bedd2041e79ed3754dcc5319db",
"partnerId": "P80000001",
"reqData": {
"issuerType": 1,
"issuerId": "9915",
"ticketDesc": "10减2元券",
"startTime": "2023-03-10",
"endTime": "2023-03-21",
"status": 0,
"hostInstNo": "",
"currPage": 1,
"pageSize": 100
},
"signType": "MD5",
"timestamp": "201809112345",
"sign": "EF7B56F75FA05FA07C8DB189518F0069"
}, null, 4)

可以看见,这段代码是没有格式化的,但是输出的结果却是正常空格格式化的。

这就是今天要说的关于JSON.stringify()的用法之一。

一、关于JSON.stringify的几个特性

1、JSON.stringify在处理undefined、函数、symbol、正则、Error特殊值时的不同表现

(1)、当undefined、函数、symbol三个特殊值作为对象属性值时:

javascript 复制代码
JSON.stringify({
    one: 'aaa',
    two: undefined,
    three: Symbol('333'),
    four: function(){
        return 1
    }
})

// 输出结果
'{"one":"aaa"}'

可以得出结论:当undefined、函数、symbol作为对象属性值时,JSON.stringify()会直接直接忽略掉

(2)、当undefined、函数、symbol三个特殊值作为数组元素时:

javascript 复制代码
JSON.stringify([1, 2, undefined, Symbol(3), function(){return 4}])

// 输出结果:
'[1,2,null,null,null]'

可以得出结论:当undefined、函数、symbol作为数组元素时,JSON.stringify()会直接将其序列化为null

(3)、当undefined、函数、symbol三个特殊值单独序列化时:

javascript 复制代码
JSON.stringify(undefined)
// 输出结果
undefined

JSON.stringify(Symbol('123'))
// 输出结果
undefined

JSON.stringify(function(){return true})
// 输出结果
undefined

可以得出结论:当undefined、函数、symbol单独进行序列化时,JSON.stringify()会直接将其序列化为undefined

(4)、当存在正则、Error对象时,无论是作为对象值、数组元素还是单独序列化,都只会返回空对象

css 复制代码
let obj = {
    a: 'a',
    b: 'b',
    reg: new RegExp('\w+'),
    err: new Error('error')
}
JSON.stringify(obj)

// 输出结果
'{"a":"a","b":"b","reg":{},"err":{}}' 

根据其这一特性,我们日常在使用深拷贝方法或者进行序列化的时候,就要考虑是否有这几种特殊类型值存在,如果存在需要用特殊方法处理(后边会介绍)

2、当转换值中有toJSON()方法时,序列化的结果就是该方法的返回值,会忽略掉其他属性。

javascript 复制代码
JSON.stringify({
    name: 'lilei',
    age: 12,
    toJSON: function(){
        return 'hanmeimei 14'
    }
})

// 输出结果
'"hanmeimei 14"'

3、对于Date的值,JSON.stringify()会正常输出

css 复制代码
JSON.stringify({time: new Date()})

// 输出结果
'{"time":"2024-04-01T08:18:39.722Z"}'

可以看到对于Date输出了正常的日期值,是因为Date对象内部有自己的toJSON()方法,相当于Date对象被当做了普通的字符串去处理。

4、对于NaN、Infinity、null,无论是作为对象的值、数组的元素还是单独序列化,都会被当做null

json 复制代码
JSON.stringify({
    one: NaN,
    twu: Infinity,
    three: null
})

// 输出结果
'{"one":"null","two":null,"three":null}'

5、如果存在属性可枚举和不可枚举的对象,仅会序列化可枚举属性

php 复制代码
JSON.stringify(
    Object.create(
        null,
        {
            a: { value: 'aaa', enumerable: false },
            b: { value: 'bbb', enumerable: true }
        }
    )
)

// 输出结果
'{"b":"bbb"}'

6、当使用JSPN.parse(JSON.stringify())进行对象拷贝时,注意循环引用问题,关于解决方法可以通过添加序列号、删除属性值、控制序列化深度等,具体情况具体分析。

二、关于JSON.stringify()的第二个和第三个参数

1、第二个参数replacer

第二个参数可以是一个数组,也可以是一个函数。

(1)当是数组时,数组的值代表着将被序列化成JSON字符串的属性名。

csharp 复制代码
let obj = {
    name: 'json',
    params: 'stringfy params'
}
JSON.stringify(obj, ['name'])

// 输出结果
'{"name":"json"}'

(2)当时函数时,可以改变上边说的相关特性,对于undefined、Symbol、函数类型(无论作为对象值、还是数组元素)、正则、Error,可以使其返回定义的值

javascript 复制代码
const data = {
  a: "aaa",
  b: undefined,
  c: Symbol("234"),
  fn: function() {
    return true;
  },
  reg: new RegExp('\w+'),
  err: new Error('error')
};

// 使用 replacer 参数作为函数时
JSON.stringify(data, (key, value) => {
  switch (true) {
    case  typeof value === "undefined":
      return "undefined";
    case  typeof value === "symbol":
      return value.toString();
    case  typeof value === "function":
      return value.toString();
    case  Object . prototype . toString . call ( value) === "[object Error]":
      return 'error';
    case  Object . prototype . toString . call (value) === "[object RegExp]" :
      return 'regexp';
    default:
      break;
  }
  return value;
})

// 输出结果
'{"a":"aaa","b":"undefined","c":"Symbol(234)","fn":"function() {\n    return true;\n  }","reg":"regexp","err":"error"}'
// 未使用第二个参数时,只会输出 "{"a":"aaa"}" 

特殊情况:如果对象的属性是个Symbol,那么这个属性值也会直接被忽略掉,即使采用函数方法强制返回值也是无效的。

javascript 复制代码
JSON.stringify({[Symbol.for("json")]: "symbolstring"}, function(k, v) {
    if (typeof k === "symbol") {
      return v;
    }
})

// 输出结果
undefined

注意:replacer被传入为函数时,函数参数对应的第一对key/value并不是对象的第一个属性,key值是一个空字符串,value值是整个对象键值对;从第二个开始的key/value才是对应数据的属性值。

yaml 复制代码
const data = {  a : 2 ,  b : 3 ,  c : 4 ,  d : 5  }; JSON . stringify (data, ( key, value ) => {  console . log ( 'key:' , key, 'value:' , value);  return value; })

// console打印出内容
key:  value: {a: 2, b: 3, c: 4, d: 5}
key: a value: 2
key: b value: 3
key: c value: 4
key: d value: 5

2、第三个参数

第三个参数space主要用来控制结果的间距,或者是添加一些特殊标识。

javascript 复制代码
let obj = {
a: 1, b: 2, c: 3, d: 4
}
JSON.stringify(obj, null, 2)
JSON.stringify(obj, null, '**')

// 输出结果
' {
  "a" : 1 ,
  "b" : 2 ,
  "c" : 3 ,
  "d": 4
} '

'{
**"a": 1,
**"b": 2,
**"c": 3,
**"d": 4
}'

注意:space是有长度限制的,最大长度是10,但是超过10也不会报错。
如果传入的是数值并且超过10,其最多只会缩进10个空格; 如果传入的是字符串并且长度超过10,则只会截取前十个字符;

虽然日常开发中使用比较少,但是大概知道用法,在使用的时候还是很方便的~

相关推荐
passerby606119 分钟前
完成前端时间处理的另一块版图
前端·github·web components
掘了26 分钟前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅29 分钟前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅1 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅1 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment1 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅2 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊2 小时前
jwt介绍
前端
爱敲代码的小鱼2 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax
Cobyte2 小时前
AI全栈实战:使用 Python+LangChain+Vue3 构建一个 LLM 聊天应用
前端·后端·aigc