JavaScript對(duì)象與JSON格式的轉(zhuǎn)換及JSON.stringify和JSON.parse的使用方法
JSON處理
JSON(JavaScript Object Notation)是JavaScript表達(dá)值和對(duì)象的通用數(shù)據(jù)格式,其本質(zhì)就是符合一定規(guī)范的字符串。由于JSON的優(yōu)良特性,非常容易和其他語(yǔ)言進(jìn)行數(shù)據(jù)交換,尤其在前后端交互方面。即使我們前端使用JavaScript,后端使用Java/PHP/Python同樣可以使用JSON格式的數(shù)據(jù)輕松交換。
JSON.stringify
JavaScript為我們提供了簡(jiǎn)單的方法可以實(shí)現(xiàn)對(duì)象和字符串之間的轉(zhuǎn)化。
JSON.stringify將對(duì)象轉(zhuǎn)為JSON字符串;JSON.parse將JSON字符串轉(zhuǎn)為對(duì)象;
例如,我們把一個(gè)對(duì)象Dog使用 JSON.string轉(zhuǎn)為JSON字符串:
let Dog = {
name:'Peter',
age:187,
gender:'male',
hands:['hand01','hand02','hand03','hand04'],
childs:[
{
name:'little peter01',
age:2,
gender:'male',
hands:['hand01','hand02','hand03','hand04'],
childs:[]
},
{
name:'little peter02',
age:3,
gender:'male',
hands:['hand01','hand02','hand03','hand04'],
childs:[]
}
]
}
let dogJson = JSON.stringify(Dog)
console.log(typeof dogJson)
console.log(dogJson)代碼的執(zhí)行效果:

可見,使用JSON.stringify(obj)方法會(huì)返回該對(duì)象obj的JSON字符串?dāng)?shù)據(jù),這個(gè)轉(zhuǎn)換的過程可以稱作JSON編碼(JSON-encoded)、序列化(serialized),亦或者編組化(marshalled)。當(dāng)對(duì)象轉(zhuǎn)為普通的字符串后,我們就可以以普通數(shù)據(jù)的格式存儲(chǔ)、傳遞這些數(shù)據(jù)。
如果我們把這些字符串寫入數(shù)據(jù)庫(kù),就相當(dāng)于把JavaScript對(duì)象存進(jìn)了數(shù)據(jù)庫(kù)。
注意:
JSON編碼的對(duì)象統(tǒng)一使用雙引號(hào),沒有單引號(hào)和反引號(hào);- 對(duì)象的屬性名也用雙引號(hào),這是強(qiáng)制的;
JSON已經(jīng)發(fā)展成為了獨(dú)立的數(shù)據(jù)規(guī)范,因此歸屬于JavaScript語(yǔ)言本身的非數(shù)據(jù)屬性會(huì)被JSON.stringify跳過。
包括:
- 對(duì)象方法;
- Symbol類型
- undefined的屬性
let user = {
sayHello(){//函數(shù)被忽略
console.log('hello world');
},
[Symbol('id')]:996996,//Symbol被忽略
val:undefined//undefined值被忽略
}
console.log(JSON.stringify(user))
代碼執(zhí)行效果:

可以看到,里面啥也沒有。
stringify的限制
并非所有的對(duì)象都能轉(zhuǎn)為JSON格式,如果對(duì)象之間存在循環(huán)引用,就會(huì)導(dǎo)致轉(zhuǎn)換失敗。
let father = {}
let son = {}
father.son = son
son.father = father
JSON.stringify(father)代碼執(zhí)行結(jié)果:

這里出現(xiàn)錯(cuò)誤的原因就是存在對(duì)象間的循環(huán)引用,Father引用了Son,而Son又反過來引用了Father。

排除和替換
如果我們只希望將對(duì)象的個(gè)別屬性轉(zhuǎn)為JSON格式,或者擺出循環(huán)應(yīng)用中的屬性,應(yīng)該怎么做呢?
JSON.stringify已經(jīng)為我們提供了解決方法:
let json = JSON.stringify(obj[,replacer,space])
參數(shù)解讀:
obj:要編碼的對(duì)象replacer:要編碼的屬性數(shù)組或者映射函數(shù)function(k,v)space:用于格式化的空格數(shù)量
舉個(gè)例子:
let father = {
name:'father',
age:28
}
let son = {
name:'son',
age:4
}
father.son = son;
son.father = father;
console.log(JSON.stringify(father,['name','age']))代碼的執(zhí)行結(jié)果如下:

如果我們?cè)诘诙€(gè)參數(shù)傳入一個(gè)數(shù)組,那么JSON.stringify就會(huì)只把數(shù)組中的名稱轉(zhuǎn)為JSON格式,這樣計(jì)算對(duì)象存在循環(huán)引用,同樣能夠成功的轉(zhuǎn)格式。
如果我們希望序列化出循環(huán)應(yīng)用外的所有對(duì)象屬性,只需要把對(duì)象的所有屬性名寫入數(shù)組即可,這對(duì)對(duì)象的子對(duì)象同樣生效。
舉個(gè)例子:
let father = {
name:'father',
age:28,
car:{
car_name : "BYD",
car_age:3,
}
}
console.log(JSON.stringify(father,['name','car','car_name']))代碼執(zhí)行結(jié)果:

但是,還存在一個(gè)問題,如果對(duì)象屬性特別多,可能數(shù)組就會(huì)非常長(zhǎng),代碼也會(huì)很冗長(zhǎng)。
這種情況下就需要使用映射函數(shù)
映射函數(shù)
我們可以創(chuàng)建一個(gè)函數(shù),代替數(shù)組作為replacer,這個(gè)函數(shù)接收(key,value)作為參數(shù),并決定如何序列化對(duì)應(yīng)的屬性。
例如,在解決循環(huán)引用的時(shí)候,我們排除引用屬性:
let father = {
name:'father',
age:28,
car:{
car_name : "BYD",
car_age:3,
}
}
let son = {
name:'son',
age:4
}
father.son = son;
son.father = father;
console.log(JSON.stringify(father,function replacer(key,value){
console.log(`${key}:${value}`)
return (key=='son')?undefined:value;
}))代碼執(zhí)行結(jié)果如下:

由于值為undefined的屬性會(huì)被JSON.stringify忽略,這樣我們就可以輕松的排除所有不希望出現(xiàn)的屬性了。
格式化使用的空格數(shù)量
JSON.stringify(value, replacer, spaces)的第三個(gè)參數(shù)spaces可以指定JSON字符串的縮進(jìn)空格數(shù),常用的數(shù)值有2、4兩種,相信童鞋們已經(jīng)在編輯代碼的時(shí)候有過修改縮進(jìn)tab空格數(shù)的經(jīng)歷了。
在上文案例中,我們沒有指定縮進(jìn)空格數(shù)量,所以格式化后的JSON字符串都是沒有格式的。
舉個(gè)例子:
let Dog = {
name:'Peter',
age:187,
gender:'male',
hands:['hand01','hand02','hand03','hand04'],
childs:[
{
name:'little peter01',
age:2,
gender:'male',
hands:['hand01','hand02','hand03','hand04'],
childs:[]
},
{
name:'little peter02',
age:3,
gender:'male',
hands:['hand01','hand02','hand03','hand04'],
childs:[]
}
]
}
let dogJson = JSON.stringify(Dog,null,2)
console.log(dogJson)代碼的執(zhí)行結(jié)果:

對(duì)比本文的第一個(gè)案例,是不是這樣的縮進(jìn)看起來好看多了呢?
自定義toJSON方法
在之前的文章中,我們講到每個(gè)對(duì)象都有的toString方法,當(dāng)進(jìn)行格式轉(zhuǎn)換時(shí)會(huì)自動(dòng)調(diào)用。和toString一樣,對(duì)象的toJSON方法會(huì)在序列化的時(shí)候調(diào)用,我們可以通過重寫這個(gè)方法改變序列化的方式。
例如:
let dog = {
name : 'peter',
age:18
}
console.log(JSON.stringify(dog))
dog.toJSON = function(){
return this.age;
}
console.log(JSON.stringify(dog))代碼執(zhí)行結(jié)果:

我們可以看到,在重寫了對(duì)象的toJSON方法后,使用stringify的結(jié)果發(fā)生了改變。
我們可以根據(jù)自己的需要重寫toJSON方法,從而達(dá)到自己的目的。
JSON.parse
上文講到了如何使用JSON.stringify把對(duì)象轉(zhuǎn)為JSON格式的字符串,這里就詳細(xì)介紹如何把JSON字符串轉(zhuǎn)為對(duì)象。
語(yǔ)法:
let obj = JSON.parse(str,[reviver])
str 要解析的 JSON 字符串。
reviver 可選的函數(shù) function(key,value),該函數(shù)將為每個(gè) (key, value) 對(duì)調(diào)用,并可以對(duì)值進(jìn)行轉(zhuǎn)換。
例如:
let str_arr = '[1,2,3]'//數(shù)組字符串 let arr = JSON.parse(str_arr) console.log(typeof arr)
代碼執(zhí)行結(jié)果:

對(duì)于復(fù)雜的嵌套對(duì)象:
let str_obj = `{
"name": "Peter",
"age": 187,
"gender": "male",
"hands": [
"hand01",
"hand02",
"hand03",
"hand04"
],
"childs": [
{
"name": "little peter01",
"age": 2,
"gender": "male",
"hands": [
"hand01",
"hand02",
"hand03",
"hand04"
],
"childs": []
},
{
"name": "little peter02",
"age": 3,
"gender": "male",
"hands": [
"hand01",
"hand02",
"hand03",
"hand04"
],
"childs": []
}
]
}`
let obj = JSON.parse(str_obj)
console.log(obj.name)代碼執(zhí)行結(jié)果:

注意:
JSON不支持注釋,在JSON中添加注釋時(shí)錯(cuò)誤的行為有一種名為JSON5的格式,可以有不加引號(hào)的鍵、允許注釋,但是這是獨(dú)立的庫(kù),補(bǔ)上官方標(biāo)準(zhǔn)。
常規(guī)的
JSON格式嚴(yán)格,這樣是為了保證數(shù)據(jù)的可靠、快速解析算法
使用reviver
既然JSON.parse能夠直接轉(zhuǎn)字符串為對(duì)象,為啥還要再搞reviver呢?
場(chǎng)景舉例:
如果我們有一個(gè)對(duì)象字符串如下:
// title: (meetup title), date: (meetup date)
let str = '{"title":"Conference","date":"2017-11-30T12:00:00.000Z"}';現(xiàn)在我們要將它轉(zhuǎn)為對(duì)象,存在什么問題呢?
let str = '{"title":"Conference","date":"2017-11-30T12:00:00.000Z"}';
let obj = JSON.parse(str)
obj.date.getDate();//Error代碼執(zhí)行結(jié)果如下:

造成這種結(jié)果的原因是date屬性被轉(zhuǎn)為了字符串,而不是Date對(duì)象。
這個(gè)時(shí)候就需要我們使用reviver函數(shù)將date轉(zhuǎn)為Date對(duì)象:
let str = '{"title":"Conference","date":"2017-11-30T12:00:00.000Z"}';
let obj = JSON.parse(str,function(key,value){
if(key=='date')return new Date(value)
return value
})
obj.date.getDate();代碼執(zhí)行效果:

順便說一下,這也適用于嵌套對(duì)象:
let schedule = `{
"meetups": [
{"title":"Conference","date":"2017-11-30T12:00:00.000Z"},
{"title":"Birthday","date":"2017-04-18T12:00:00.000Z"}
]
}`;
schedule = JSON.parse(schedule, function(key, value) {
if (key == 'date') return new Date(value);
return value;
});
alert( schedule.meetups[1].date.getDate() ); // 正常運(yùn)行了!總結(jié)
- JSON是一種數(shù)據(jù)格式,有獨(dú)立的標(biāo)準(zhǔn)和大多數(shù)編程語(yǔ)言的支持
- JSON支持Object、array、string、number、boolean和nullJ
- SON.stringify
- JSON.parse
到此這篇關(guān)于JavaScript對(duì)象與JSON格式的轉(zhuǎn)換及JSON.stringify和JSON.parse的使用方法的文章就介紹到這了,更多相關(guān)JS與JSON格式轉(zhuǎn)換內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
javascript引用類型之時(shí)間Date和數(shù)組Array
引用類型的值(對(duì)象)其實(shí)就是引用類型的一個(gè)實(shí)例,接下來,通過本篇文章給大家介紹javascript引用類型之時(shí)間Date和數(shù)組Array,需要的朋友可以參考下2015-08-08
ES6實(shí)現(xiàn)的遍歷目錄函數(shù)示例
這篇文章主要介紹了ES6實(shí)現(xiàn)的遍歷目錄函數(shù),涉及ES6文件目錄的遍歷、讀取、回調(diào)函數(shù)及json相關(guān)操作技巧,需要的朋友可以參考下2017-04-04
關(guān)于JS通過google翻譯插件實(shí)現(xiàn)多語(yǔ)言版本
這篇文章主要介紹了JS通過google翻譯插件實(shí)現(xiàn)多語(yǔ)言版本,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-06-06
JavaScript中的類與實(shí)例實(shí)現(xiàn)方法
這篇文章主要介紹了JavaScript中的類與實(shí)例實(shí)現(xiàn)方法,非常巧妙的模擬了類與實(shí)例的實(shí)現(xiàn)過程,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-01-01
javascript中如何將字符串轉(zhuǎn)換成數(shù)字
這篇文章主要介紹了javascript中如何將字符串轉(zhuǎn)換成數(shù)字問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-02-02

