小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
前言
先问一个问题,下面的obj是JSON对象吗:
{
name:"tom",
[Symbol.for("sex")]: 1
}
答案:
不是,是对象字面量。
JSON和对象字面量
JSON
- 键一定要用双引号(也就是字符串)
- 值只能使是:数字,布尔,数组,null,对象,字符串。 值如果是字符串也要用双引号
如下是对象
{
"name": "tom",
"age": 10
}
对象字面量
如下均是对象字面量,不是JSON
{
"name": "tom",
"age": undefined // 只能是数字,布尔,数组,null,对象,字符串
}
{
name:"tom",
[Symbol.for("sex")]: 1 // 键只能是字符串
}
{
name:"tom",
[Symbol.for("sex")]: 1, // 多余,的
}
JSON.parse()
方法用来解析JSON字符串,构造由字符串描述的JavaScript值或对象。
JSON.parse(text[, reviver])
第二个参数 reviver
大家肯定都使用过JSON.parse, 可是其有第二个参数,有多少人在意过呢?
reviver是一个函数,有两个参数:
- k: 当前要转换属性键
- v: 当前要转换的属性值
如果 reviver 返回 undefined,则当前属性会从所属对象中删除,如果返回了其他值,则返回的值会成为当前属性新的属性值。
还需要注意两点:
遍历顺序
这个函数的遍历顺序依照:从最内层开始,按照层级顺序,依次向外遍历。
var jsonStr = `{
"name": "牙膏",
"count": 10,
"orderDetail": {
"createTime": 1632996519781,
"orderId": 8632996519781,
"more": {
"desc": "描述"
}
}
}`
JSON.parse(jsonStr, function(k, v){
console.log("key:", k);
return v;
})
// key: name
// key: count
// key: createTime
// key: orderId
// key: desc
// key: more
// key: orderDetail
// key:
this
this是变化的,是当前属性key所属的上一级对象,看一个栗子就明白了。
var jsonStr = `{
"name": "牙膏",
"count": 10,
"orderDetail": {
"createTime": 1632996519781,
"orderId": 8632996519781
}
}`
JSON.parse(jsonStr, function(k, v){
console.log("key:", k, ",this:", this);
return v;
})
// key: name ,this: {name: '牙膏', count: 10, orderDetail: {…}}
// key: count ,this: {name: '牙膏', count: 10, orderDetail: {…}}
// key: createTime ,this: {createTime: 1632996519781, orderId: 8632996519781}
// key: orderId ,this: {createTime: 1632996519781, orderId: 8632996519781}
// key: orderDetail ,this: {name: '牙膏', count: 10, orderDetail: {…}}
// key: ,this: {"": {…}}
JSON.stringify()
方法将一个 JavaScript 对象或值转换为 JSON 字符串。
语法
JSON.stringify(value[, replacer [, space]])
其还有第二个参数和第三个参数。
replacer可选
如果该参数是一个函数,则在序列化过程中,被序列化的值的每个属性都会经过该函数的转换和处理;如果该参数是一个数组,则只有包含在这个数组中的属性名才会被序列化到最终的 JSON 字符串中;如果该参数为 null 或者未提供,则对象所有的属性都会被序列化。
space可选
指定缩进用的空白字符串,用于美化输出(pretty-print);如果参数是个数字,它代表有多少的空格;上限为10。该值若小于1,则意味着没有空格;如果该参数为字符串(当字符串长度超过10个字母,取其前10个字母),该字符串将被作为空格;如果该参数没有提供(或者为 null),将没有空格。
replacer对数据转换很有用
space对美化格式输出非常有用
限制
- 循环引用会报错,
- BigInt的值也会报错
其他的:
JSON.stringify毕竟是把输入转为字符串,所以有很多的限制,比如 undefined的值会被忽视, Symbol的键会被忽视,NaN 和 Infinity 格式的数值及 null 都会被当做 null,Date会变为ISO字符串等等。
更多参见 developer.mozilla.org/zh-CN/docs/…
toJSON
如果一个被序列化的对象拥有 toJSON 方法,那么该 toJSON 方法就会覆盖该对象默认的序列化行为。
var prodcut = {
"name": "牙膏",
"count": 10,
"orderDetail": {
"createTime": 1632996519781,
"orderId": 8632996519781
},
toJSON(){
return {
name: "牙膏"
}
}
}
JSON.stringify(prodcut) // '{"name":"牙膏"}
小结
今天你收获了吗?