詳解JSON.parse和JSON.stringify用法
JSON格式,(簡寫JavaScript Object Notation),是一種用于數(shù)據(jù)交換的文本格式,書寫簡單。
基于JavaScript原生語法,能夠序列化對象、數(shù)組、數(shù)值、字符串、布爾值和 null。
在ES5中,增加了一個(gè)JSON對象,專門用來處理JSON格式的數(shù)據(jù)。
JSON是一個(gè)對象,但只有兩個(gè)方法:parse
和 stringify
,不能作為構(gòu)造函數(shù),也無屬性。
typeof JSON === 'object'
JSON.parse
JSON.parse()
用來解析JSON字符串,得到對應(yīng)的JavaScript值或?qū)ο蟆?/p>
JSON.parse('{}') // {} JSON.parse('true') // true JSON.parse('null') // null
JSON.parse 語法
JSON.parse(text[, reviver])
- text:要被解析成的字符串。
如果傳入數(shù)字則會(huì)轉(zhuǎn)換成十進(jìn)制數(shù)字輸出。
如果傳入布爾值則直接輸出。
如果傳入null則輸出null。
不支持其他類型的值,否則報(bào)錯(cuò)。
- reviver: 可選,轉(zhuǎn)換器, 可以用來修改解析生成的原始值。
返回值: JavaScript對象/值, 對應(yīng)給定JSON文本的對象/值。
reviver 參數(shù)
reviver函數(shù),用于轉(zhuǎn)換處理解析到的JavaScript值,處理完后返回最終的結(jié)果。
轉(zhuǎn)換過程:
- 解析的值本身和它可能包含的所有屬性,按照一定遍歷順序分別調(diào)用reviver函數(shù),屬性名和值作為參數(shù)兩個(gè)參數(shù)
key
和value
傳入。遍歷順序:按照層級,從內(nèi)往外遍歷,最終到達(dá)最頂層,則是解析值本身。
- reviver返回undefined,則刪除該對象,如果返回了其他值,則該值會(huì)成為當(dāng)前屬性的新值。
- 當(dāng)遍歷到最頂層時(shí),因?yàn)闆]有屬性了,參數(shù)key是空字符串
''
,參數(shù)value則是當(dāng)前解析值。
對于reviver函數(shù)的兩個(gè)參數(shù) key
和 value
,不同的數(shù)據(jù)類型:
- 基本值類型數(shù)據(jù)(string、number、boolean)和null,以及空對象
{}
和空數(shù)組[]
:則key是空字符串,value是對應(yīng)解析值。
因?yàn)橐呀?jīng)是最頂層,并沒有別的屬性。
- Object對象:
則key和value都存在,與屬性名和值各自對應(yīng)。
最頂層會(huì)返回一個(gè)參數(shù)key為空的值。
- 數(shù)組:
key對應(yīng)數(shù)組索引,value對應(yīng)元素值。
最頂層會(huì)返回一個(gè)參數(shù)key為空的值。
基本類型的轉(zhuǎn)換:
JSON.parse('5', function (key, value) { console.log(`key:${key}, value:${value}`) }) // key:, value:5 JSON.parse('null', function (key, value) { console.log(`key:${key}, value:${value}`) }) // key:, value:null JSON.parse('{}', function (key, value) { console.log(`key:${key}, value:`, value) }) // key:, value:{}
Object對象和數(shù)組:
JSON.parse('[1, 2]', function (key, value) { console.log(`key:${key}, value:`, value) }) // key:0, value: 1 // key:1, value: 2 // key:, value: (2)?[empty × 2] JSON.parse('{ "user": "張三", "info": { "age": 25, "sex": 1 } }', function (key, value) { console.log(`key:${key}, value::`, value) }) // key:user, value:: 張三 // key:age, value:: 25 // key:sex, value:: 1 // key:info, value:: {} // key:, value:: {}
數(shù)據(jù)處理:
JSON.parse('[1, 2]', function (key, value) { if(key === '') { return value } return value + 3 }) // [4, 5]
JSON.parse 特性
在解析JSON字符串的時(shí)候,需要注意到JSON格式的一些規(guī)范,不然就容易報(bào)錯(cuò)。
JSON數(shù)據(jù)對值的類型和格式,都有嚴(yán)格的規(guī)定,具體的規(guī)則如下:
- 該方法使用字符串類型JSON格式數(shù)據(jù)。
該方法也支持?jǐn)?shù)字、布爾值和null三個(gè)類型的值,轉(zhuǎn)換出對應(yīng)的字面值。
不支持其他類型。
JSON.parse('"中國"') // '中國' JSON.parse(null) // null JSON.parse(111.) // 111 JSON.parse(0x12) // 18 JSON.parse(true) // true JSON.parse([]) // Uncaught SyntaxError: Unexpected end of JSON input
- 字符串必須使用雙引號,不能使用單引號。
JSON.parse('"String"') // 'String' JSON.parse('\'String\'') // Uncaught SyntaxError: Unexpected token ' in JSON at position 0
- 只支持十進(jìn)制的字符串,但小數(shù)點(diǎn)后必須跟上數(shù)字。
JSON.parse('111') // 111 JSON.parse('0x12') // Uncaught SyntaxError: Unexpected token x in JSON at position 1 JSON.parse('111.232') // 111.232 JSON.parse('111.') // Uncaught SyntaxError: Unexpected end of JSON input
- 不能使用undefined、Symbol和BigInt,數(shù)字也不支持NaN、Infinity和-Infinity,都會(huì)報(bào)錯(cuò)。
JSON.parse(undefined) // Uncaught SyntaxError: Unexpected token u in JSON at position 0 JSON.parse(Symbol()) // Uncaught TypeError: Cannot convert a Symbol value to a string JSON.parse('12n') // Uncaught SyntaxError: Unexpected token n in JSON at position 2
- 復(fù)合類型,只能是:
[]
和{}
這樣的字面量。不能使用對象構(gòu)造函數(shù),因?yàn)闀?huì)當(dāng)作執(zhí)行語句,不支持。
不能使用Object和Array,也不能是函數(shù)、RegExp對象、Date對象、Error對象等。
JSON.parse('[]') // [] JSON.parse('Object()') // Uncaught SyntaxError: Unexpected token O in JSON at position 0
- 對象的屬性名必須使用雙引號。
JSON.parse('{"key": 1 }') // {key: 1} JSON.parse('{key: 1 }') // Uncaught SyntaxError: Unexpected token k in JSON at position 1
- 數(shù)組或?qū)ο笞詈笠粋€(gè)成員的后面,不能加逗號。
JSON.parse('[1, 2, 3, 4, ]') // VM2771:1 Uncaught SyntaxError: Unexpected token ] in JSON at position 13 JSON.parse('{"key" : 1, }') // VM2779:1 Uncaught SyntaxError: Unexpected token } in JSON at position 12
- 支持unicode轉(zhuǎn)義。
JSON.parse('{"\u0066":333}') // {f: 333}
- 部分控制字符、轉(zhuǎn)義字符不支持,如'\n'、'\t'等。
JSON.parse('"\n"') // Uncaught SyntaxError: Unexpected token
解析的其他方法
將json字符串轉(zhuǎn)成json對象(js對象值),還可以使用其他方法,但是非安全代碼。
const str = '{"name":"json","age":18}' const json = JSON.parse(str) const json = eval("(" + str + ")") const json = (new Function("return " + str))()
JSON.stringify
JSON.stringify()
將一個(gè)JavaScript對象或值轉(zhuǎn)換為JSON格式字符串。
JSON.stringify 語法
JSON.stringify(value[, replacer [, space]])
- value:將要序列化成 一個(gè) JSON 字符串的JavaScript對象或值。
- replacer 可選,用于處理將要序列化的值。
- space 可選,指定縮進(jìn)用的空白字符串,用于美化輸出。
返回值: 一個(gè)表示給定值的JSON格式字符串。
replacer參數(shù)
replacer 參數(shù)可以以下三種情況:
- 如果是null、undefined或其他類型,則被忽略,不做處理;
JSON.stringify({key: 'json'}, null, null) // '{"key":"json"}' JSON.stringify({key: 'json'}, true) // '{"key":"json"}'
- 如果是一個(gè)數(shù)組,則只有包含在這個(gè)數(shù)組中的屬性名,才會(huì)最終被序列化到結(jié)果字符串中;
只對對象的屬性有效,對數(shù)組無效。
const obj = { json: 'JSON', parse: 'PARSE', stringify: 'STRINGIFY' } JSON.stringify(obj, ['parse', 'stringify']) // '{"parse":"PARSE","stringify":"STRINGIFY"}'
- 如果是一個(gè)函數(shù),被序列化的值的每個(gè)屬性都會(huì)經(jīng)過該函數(shù)的轉(zhuǎn)換和處理;
處理過程:
- 函數(shù)有兩個(gè)參數(shù),屬性名(key)和屬性值(value),都會(huì)被序列化;
- 第一次調(diào)用時(shí),key為空字符串,value則為需要序列化的整個(gè)對象;
- 第二次處理時(shí),會(huì)把第一次的的結(jié)果傳過來,后續(xù)的每一次的處理都將接收上一次處理的結(jié)果;
- 后面,將依次處理每個(gè)屬性名和屬性值,完成后返回。
JSON.stringify({ json: 1, stringify: { val: 'rr'} }, (key, value) => { console.log(`key:${key},value:`, value) return value }) // key:,value: {json: 1, stringify: {…}} // key:json,value: 1 // key:stringify,value: {val: 'rr'} // key:val,value: rr // '{"json":1,"stringify":{"val":"rr"}}'
value的類型處理:
- 如果返回基本類型字符串、數(shù)字、布爾值、null,則直接被添加到序列化后的JSON字符串中;
- 如果返回其他對象,則會(huì)在后續(xù)依次序列化該對象的屬性,如果是函數(shù)則不作處理;
- 如果返回或undefined,則不會(huì)輸出該屬性。
- 序列化數(shù)組時(shí),如果value返回undefined或者一個(gè)函數(shù),將會(huì)被null取代。
JSON.stringify({ json: 1, stringify: 'rr' }, (key, value) => { if (typeof value === 'number') { return 'ss' } return value }) // '{"json":"ss","stringify":"rr"}' JSON.stringify({ json: 1, stringify: 'rr' }, (key, value) => { if (typeof value === 'number') { value = undefined } return value }) // '{"stringify":"rr"}'
下面示例,是返回對象值時(shí)的處理:
JSON.stringify({ json: 1, stringify: 'rr' }, (key, value) => { if (typeof value === 'object') { // 第一次返回整個(gè)對象時(shí),類型是object return { parse: 'dd' } } return value }) '{"parse":"dd"}'
space 參數(shù)
space 參數(shù)用來控制結(jié)果字符串里面的間距,美化輸出??梢暂斎氲闹涤幸韵氯N情況:
- 如果是一個(gè)數(shù)字, 序列化時(shí),每一層級比上一層級多縮進(jìn)對應(yīng)數(shù)字值的空格,范圍在 1 - 10,即最小1個(gè)最大10個(gè)空格;
- 如果是一個(gè)字符串,序列化時(shí),該字符串會(huì)添加在每行前面,每一層級比上一層級多縮進(jìn)該字符串,最多是個(gè)字符,超過則截取字符串;
- 如果是null、undefined或其他類型,則被忽略,不做處理。
JSON.stringify({key: 'json'}, null, 2) // '{\n "key": "json"\n}' JSON.stringify({key: 'json', list: { str: 'str' } }, null, '|-') // '{\n|-"key": "json",\n|-"list": {\n|-|-"str": "str"\n|-}\n}' JSON.stringify({key: 'json'}, null, null) // '{"key":"json"}'
JSON.stringify 特性
- 基本類型值字符串、數(shù)字、布爾值,以及String、Boolean、Number對象值,都會(huì)轉(zhuǎn)成原始值字符串輸出。
JSON.stringify(333) // '333' JSON.stringify(true) // 'true' JSON.stringify(new String('333')) //'"333"' JSON.stringify(Boolean(true)) // 'true'
- 基本類型的字符串,轉(zhuǎn)換結(jié)果會(huì)帶雙引號。
因?yàn)樵谶€原時(shí),雙引號會(huì)讓JavaScript知道是字符串,而不是變量。
JSON.stringify('json') === 'json' // false JSON.stringify('json') === '"json"' // true
- undefined、函數(shù)、symbol以及XML對象:
- 出現(xiàn)在Object對象中時(shí),會(huì)被忽略;
- 出現(xiàn)在數(shù)組中時(shí),會(huì)被序列化成null;
- 單獨(dú)出現(xiàn)時(shí),會(huì)返回undefined。
JSON.stringify(Symbol()) // undefined JSON.stringify([Symbol(), Math.abs, undefined]) // '[null,null,null]' JSON.stringify({ [Symbol()]: Math.abs, key: undefined }) // '{}'
- NaN、Infinity和-Infinity等值,還有null,都會(huì)被序列化成null。
JSON.stringify(null) // 'null' JSON.stringify(NaN) // 'null'
- Object對象,以及
Map/Set/WeakMap/WeakSet
等復(fù)合類型對象,序列化時(shí)會(huì)忽略對象的不可遍歷屬性。
const obj = {} Object.defineProperties(obj, { 'json': { value: 'JSON', enumerable: true }, 'stringify': { value: 'STRINGIFY', enumerable: false } }) JSON.stringify(obj) // '{"json":"JSON"}'
- 以symbol為屬性名的屬性將被忽略。
JSON.stringify({[Symbol()]: 333}) // '{}'
- 除了數(shù)組,其他對象的屬性在序列化時(shí),順序可能會(huì)亂。
const a = { '1': 911, 'r': 822, '11': 9922} JSON.stringify(a) // '{"1":911,"11":9922,"r":822}'
- 轉(zhuǎn)換的對象如果定義了
toJSON()
方法,則該方法的返回值就是轉(zhuǎn)換對象的序列化結(jié)果。該過程會(huì)忽略其他屬性。
const a = { key: 'json' } a.toJSON = () => 'JSON' JSON.stringify(a) // '"JSON"'
- RegExp對象、Error對象都會(huì)序列化為空對象字符串。
JSON.stringify(/\d/) // "{}" JSON.stringify(new Error()) // "{}"
想要序列化相應(yīng)對象,需要設(shè)置實(shí)現(xiàn)toJSON方法才行。
RegExp.prototype.toJSON = RegExp.prototype.toString JSON.stringify(/\d/) // '"/\\\\d/"'
- Date對象已經(jīng)定義了toJSON(),并將其轉(zhuǎn)換為string字符串,因此可被序列化。
同
Date.toISOString()
。
JSON.stringify(new Date()) // '"2021-12-31T02:24:05.477Z"'
- 循環(huán)引用的對象執(zhí)行此方法,會(huì)拋出錯(cuò)誤。
對象之間相互引用,形成無限循環(huán)。
const a = {} a.key = a JSON.stringify(a) // Uncaught TypeError: Converting circular structure to JSON
- 轉(zhuǎn)換BigInt類型的值會(huì)拋出TypeError錯(cuò)誤。
BigInt值不能JSON序列化
JSON.stringify(12n) // Uncaught TypeError: Do not know how to serialize a BigInt
- 更好的支持unicode轉(zhuǎn)義符
const a = {'\u0066': 333} JSON.stringify(a) // '{"f":333}'
到此這篇關(guān)于詳解JSON.parse和JSON.stringify用法的文章就介紹到這了。希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
JavaScript instanceof 的使用方法示例介紹
判斷一個(gè)變量的類型嘗嘗會(huì)用 typeof 運(yùn)算符而他畢竟有些缺陷,就是無論引用的是什么類型的對象,它都返回object,這時(shí)就要用到instanceof來檢測某個(gè)對象是不是另一個(gè)對象的實(shí)例2013-10-10js限制文本框輸入長度兩種限制方式(長度、字節(jié)數(shù))
在實(shí)際應(yīng)用中根據(jù)需要會(huì)用到文本框限制字符長度,以些新手朋友有們可能還不清楚如何應(yīng)付,本人搜集整理了一些常用技巧,曬出來和大家分享一下,希望可以幫助你們2012-12-12javascript學(xué)習(xí)筆記_淺談基礎(chǔ)語法,類型,變量
下面小編就為大家?guī)硪黄猨avascript學(xué)習(xí)筆記_淺談基礎(chǔ)語法,類型,變量。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-09-09你必須知道的JavaScript 變量命名規(guī)則詳解
在編寫代碼的時(shí)候難免涉及到變量的命名問題,不能只要求變量名的語法正確,而忽略了變量命名對代碼可讀性的影響2013-05-05一個(gè)可以兼容IE FF的加為首頁與加入收藏實(shí)現(xiàn)代碼
一個(gè)可以兼容IE FF的加為首頁與加入收藏 好不容易找到,收藏起來。2009-11-11