一直都在用JSON.stringify()和JSON.parse(),但是从来没有去留意过一些细节内容,上礼拜面试的时候做笔试题,让我写JSON.stringify的返回值,直接给我打懵了,回来赶紧补了一下知识黑洞,现在总结一下,如果有什么不对的地方,欢迎大家指出
一、什么是JSON
JSON 是一种按照 JavaScript 对象语法的数据格式,这是 Douglas Crockford 推广的。虽然它是基于 JavaScript 语法,但它独立于 JavaScript
---MDN
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式。它以易于阅读和编写的文本格式表示结构化数据。它基于JavaScript语言的一个子集,但现在已经成为一种独立于编程语言的通用数据格式。
二、JSON的用途
JSON 可以作为一个对象或者字符串存在,前者用于解读 JSON 中的数据,后者用于通过网络传输 JSON 数据。
---MDN
- 数据传输:JSON常用于客户端和服务器之间的数据传输。通过将数据转换为JSON格式,可以方便地在网络上进行传输,并且可以被各种编程语言和平台解析和处理。
- 配置文件:JSON格式可以用于存储和传输配置信息。许多应用程序使用JSON格式来保存各种配置选项,例如Web应用程序的配置文件、软件的设置文件等。
- API数据交换:在Web开发中,许多API(Application Programming Interface)使用JSON格式作为数据交换的标准。当客户端向服务器请求数据或发送数据时,通常使用JSON格式来表示请求和响应的数据。
- 存储和持久化:JSON格式可以用于将数据存储到数据库或文件中。许多数据库系统支持将JSON格式作为数据类型或存储格式,使得可以方便地将结构化数据以JSON形式进行存储和检索。
- 配置数据传递:JSON格式可以用于在不同组件之间传递配置信息。例如,在微服务架构中,各个微服务之间可以使用JSON格式来传递配置信息,以实现松耦合和灵活性。
三、JSON的书写规则
-
数据类型:JSON支持以下数据类型:
- 字符串(使用双引号括起来):"Hello World"
- 数字:42
- 布尔值:true 或 false
- 数组(使用方括号括起来):[1, 2, 3]
- 对象(使用花括号括起来):{"name": "John", "age": 30}
- null
-
键值对:JSON使用键值对的方式来表示数据。键是一个字符串,值可以是任何合法的JSON数据类型。键和值之间使用逗号(,)分隔,最后一个键值对不能有(,)。
示例:
{"name": "John", "age": 30} -
对象:JSON对象由一对花括号({})包围,里面包含零个或多个键值对。键值对之间使用逗号(,)分隔,。
示例:
{ "name": "John", "age": 30, "isStudent": true } -
数组:JSON数组由一对方括号([])包围,里面包含零个或多个值。值之间使用逗号(,)分隔。
示例:
[1, 2, 3, 4] -
嵌套:JSON数据可以嵌套使用,可以在一个JSON对象中嵌套另一个JSON对象或数组。
示例:
{ "name": "John", "age": 30, "hobbies": ["reading", "running"], "address": { "street": "123 Main St", "city": "New York" } } -
注释:JSON本身不支持注释,因为它是一种数据交换格式而不是编程语言。
四、JSON.stringify()
作用:将一个js对象转为JSON字符串
语法:JSON.stringify(value[, replacer [, space]])
value(可选):要转换的js对象,可不填写
console.log(JSON.stringify()) //不会报错 输出undefined
replacer(可选):
1、如果该参数是一个函数,则在序列化过程中,被序列化的值的每个属性都会经过该函数的转换和处理;
2、如果该参数是一个数组,则只有包含在这个数组中的属性名才会被序列化到最终的 JSON 字符串中;
3、如果该参数为 null 或者未提供,则对象所有的属性都会被序列化。
let obj={
a:1,
b:'2'
}
console.log(JSON.stringify(obj,(key,value)=>{
if(key==='a'){
return value+10
}
return value
},3))
console.log(JSON.stringify(obj,['a'],3))
输出结果:
space(可选):指定缩进用的空白字符串,用于美化输出,便于阅读;
1、如果参数是个数字,它代表有多少的空格;上限为 10。该值若小于 1,则意味着没有空格;
2、如果该参数为字符串(当字符串长度超过 10 个字母,取其前 10 个字母),该字符串将被作为空格;
3、如果该参数没有提供(或者为 null),将没有空格。
示例:
let obj={
a:1,
b:'2'
}
console.log(JSON.stringify(obj.null,3))
console.log(JSON.stringify(obj,null,'1234'))
console.log(JSON.stringify(obj,null,'1234567890123'))
输出结果:
JSON.stringfy()的转换规则
- 见人说人话,见鬼说鬼话的undefined、Symbol、function
- undefined、Symbol、function在非数组对象中---
被忽略
let obj={
a:undefined,
b:function(){},
c:Symbol()
}
console.log('非数组对象中:',JSON.stringify(obj)) // 非数组对象中:{}
- undefined、Symbol、function在数组中---
转为null
let arr = [undefined,function(){},Symbol()]
console.log(‘’数组中,JSON.stringify(arr)) //数组中:[null,null,null]
- undefined、Symbol、function单独使用---
转为undefined
let a = undefined
console.log('单独的undefined:',JSON.stringify(a)) // 单独的undefined: undefined
let b = function(){}
console.log('单独的function:',JSON.stringify(b)) // 单独的undefined: undefined
let c = Symbol()
console.log('单独的Symbol:',JSON.stringify(c)) //单独的JSON.stringify(a)JSON.stringify(a)Symbol: undefined
2.Boolean、Number、String---统一转为原始值
let b = new Boolean(true)
console.log(JSON.stringify(b)) // true
console.log(JSON.stringify([b])) // [true]
console.log(JSON.stringify({b})) // {"b":true}
let n = new Number(7)
console.log(JSON.stringify(n)) // 7
console.log(JSON.stringify([n])) // [7]
console.log(JSON.stringify({n})) // {"n":7}
let s = new String('xf')
console.log(JSON.stringify(s)) // "xf"
console.log(JSON.stringify([s])) // ["xf"]
console.log(JSON.stringify({s})) // {"s":"xf"}
3.Symbol作为key---被忽略(即便 replacer 参数中强制指定包含了它们)
let obj={
[Symbol()]:'symbol key'
}
console.log(JSON.stringify(obj)) // {}
let arr=[]
arr[Symbol()] = 7
console.log(arr) // [ [Symbol()]: 7 ]
console.log(JSON.stringify(arr)) // []
4.NaN、Infinity、null---统一转为null
let a=NaN
console.log(JSON.stringify(a)) // null
console.log(JSON.stringify([a])) // [null]
console.log(JSON.stringify({a})) // {"a":null}
let b=Infinity
console.log(JSON.stringify(b)) // null
console.log(JSON.stringify([b])) // [null]
console.log(JSON.stringify({b})) // {"b":null}
let c=null
console.log(JSON.stringify(c)) // null
console.log(JSON.stringify([c])) // [null]
console.log(JSON.stringify({c})) // {"c":null}
5.Date---统一转为字符串(调用了 toJSON())
let time=new Date()
console.log(JSON.stringify(time)) // "2023-06-01T15:32:04.436Z"
console.log(JSON.stringify([time])) // ["2023-06-01T15:32:04.436Z"]
console.log(JSON.stringify({time})) // {"time":"2023-06-01T15:32:04.436Z"}
6.有toJSON()方法--- 调用toJSON()后的返回值被序列化
let obj={
a:1,
b:'2',
toJSON:()=>{
return {
c:1,
d:'2'
}
}
}
console.log(JSON.stringify(obj)) // {"c":1,"d":"2"}
7、仅序列化可枚举属性
let obj=Object.create(null,
{
a:{
value:'a',enumerable:true
},
b:{
value:'b',enumerable:false
}
}
)
console.log(JSON.stringify(obj)) // {"a":"a"}
8、循环引用---报错
let obj1={}
let obj2={}
obj1.prop=obj2
obj2.prop1 = obj1
console.log(JSON.stringify(obj1)) // TypeError: Converting circular structure to JSON
9、BigInt---报错
let b = 10n
console.log(typeof b) // bigint
console.log(JSON.stringify(b)) //TypeError: Do not know how to serialize a BigInt
总结:
1、undefined、function、Symbol,在非数组对象中--被忽略,在数组中--null,单独使用时--undefined
2、布尔、数字、字符串的包装对象--原始值
3、Symbol作为key---被忽略
4、NaN、Infinity、null--null
5、Date--字符串
6、有toJSON()--toJSON()的返回值被序列化
7、仅序列化可枚举属性
8、存在循环引用-- 报错
9、存在bigInt类型--报错
五、JSON.parse()
作用:解析JSON字符串
语法:JSON.parse(text[, reviver])
text(必填):要被解析成js值的字符串,缺少该参数直接报错
reviver(可选):转换器,如果传入该参数 (函数),可以用来修改解析生成的原始值,调用时机在 parse 函数返回之前,解析值和text按照从最里层开始的顺序去调用本函数,本函数若返回undefined,则删除该属性,本函数的两个参数(key,value)表示属性值和属性名称,当解析到最外层(解析值text)时,key为‘’
let jsonStr='{"1": 1, "2": 2,"3": {"4": 4, "5": {"6": 6}}}'
let obj = JSON.parse(jsonStr,(k,v)=>{
console.log('key',k)
if(k===''){
return v
}
return v*10
})
console.log(obj)
输出结果:
六、自测环节
好了,知识点都罗列完毕了,最后来一道题检验一下自己的学习成果吧
let obj={
a:1,
b:'2',
c:true,
d:null,
e:undefined,
f:Symbol(),
g:function(){
console.log('obj function')
},
h:[1,'2',true,null,undefined,Symbol(),function(){console.log('array function')}],
i: new Boolean(false),
j:new Number(1),
k:new String('k'),
l:NaN,
m:Infinity,
n:-Infinity,
o:{
oo:12,
toJSON:function(){
return {name:'xf',age:14}
}
},
p:new Date(),
[Symbol()]:2,
q:new RegExp(),
r:new Error()
}
let jsonStr = JSON.stringify(obj,null,2)
console.log(jsonStr)
console.log(JSON.stringify())
console.log(JSON.parse())
答案就不写出来了,注意哦,里面隐藏了两个没有在前面提到的对象,赶紧去试试他们会返回什么值吧