详解JSON.parse和JSON.stringify用法


Posted in Javascript onFebruary 18, 2022

JSON格式,(简写JavaScript Object Notation),是一种用于数据交换的文本格式,书写简单。

基于JavaScript原生语法,能够序列化对象、数组、数值、字符串、布尔值和 null。

在ES5中,增加了一个JSON对象,专门用来处理JSON格式的数据。

JSON是一个对象,但只有两个方法:parse 和 stringify,不能作为构造函数,也无属性。

typeof JSON === 'object'

JSON.parse

JSON.parse() 用来解析JSON字符串,得到对应的JavaScript值或对象。

JSON.parse('{}') // {}
JSON.parse('true') // true
JSON.parse('null') // null

JSON.parse 语法

JSON.parse(text[, reviver])
  • text:要被解析成的字符串。

    如果传入数字则会转换成十进制数字输出。

    如果传入布尔值则直接输出。

    如果传入null则输出null。

    不支持其他类型的值,否则报错。

  • reviver: 可选,转换器, 可以用来修改解析生成的原始值。

返回值: JavaScript对象/值, 对应给定JSON文本的对象/值。

reviver 参数

reviver函数,用于转换处理解析到的JavaScript值,处理完后返回最终的结果。

转换过程:

  • 解析的值本身和它可能包含的所有属性,按照一定遍历顺序分别调用reviver函数,属性名和值作为参数两个参数 key 和 value 传入。

    遍历顺序:按照层级,从内往外遍历,最终到达最顶层,则是解析值本身。

  • reviver返回undefined,则删除该对象,如果返回了其他值,则该值会成为当前属性的新值。
  • 当遍历到最顶层时,因为没有属性了,参数key是空字符串'',参数value则是当前解析值。

对于reviver函数的两个参数 key 和 value,不同的数据类型:

  • 基本值类型数据(string、number、boolean)和null,以及空对象{}和空数组[]

    则key是空字符串,value是对应解析值。

    因为已经是最顶层,并没有别的属性。

  • Object对象:

    则key和value都存在,与属性名和值各自对应。

    最顶层会返回一个参数key为空的值。

  • 数组:

    key对应数组索引,value对应元素值。

    最顶层会返回一个参数key为空的值。

基本类型的转换:

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对象和数组:

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:: {}

数据处理:

JSON.parse('[1, 2]', function (key, value) {
  if(key === '') {
    return value
  }
  return value + 3
})
// [4, 5]

JSON.parse 特性

在解析JSON字符串的时候,需要注意到JSON格式的一些规范,不然就容易报错。

JSON数据对值的类型和格式,都有严格的规定,具体的规则如下:

  • 该方法使用字符串类型JSON格式数据。

    该方法也支持数字、布尔值和null三个类型的值,转换出对应的字面值。

    不支持其他类型。

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
  • 只支持十进制的字符串,但小数点后必须跟上数字。
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,数字也不支持NaN、Infinity和-Infinity,都会报错。
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
  • 复合类型,只能是:[] 和 {} 这样的字面量。

    不能使用对象构造函数,因为会当作执行语句,不支持。

    不能使用Object和Array,也不能是函数、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
  • 数组或对象最后一个成员的后面,不能加逗号。
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转义。
JSON.parse('{"\u0066":333}')
// {f: 333}
  • 部分控制字符、转义字符不支持,如'\n'、'\t'等。
JSON.parse('"\n"')
// Uncaught SyntaxError: Unexpected token

解析的其他方法

将json字符串转成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() 将一个JavaScript对象或值转换为JSON格式字符串。

JSON.stringify 语法

JSON.stringify(value[, replacer [, space]])
  • value:将要序列化成 一个 JSON 字符串的JavaScript对象或值。
  • replacer 可选,用于处理将要序列化的值。
  • space 可选,指定缩进用的空白字符串,用于美化输出。

返回值: 一个表示给定值的JSON格式字符串。

replacer参数

replacer 参数可以以下三种情况:

  • 如果是null、undefined或其他类型,则被忽略,不做处理;
JSON.stringify({key: 'json'}, null, null) // '{"key":"json"}'
JSON.stringify({key: 'json'}, true) // '{"key":"json"}'
  • 如果是一个数组,则只有包含在这个数组中的属性名,才会最终被序列化到结果字符串中;

    只对对象的属性有效,对数组无效。

const obj = {
  json: 'JSON',
  parse: 'PARSE',
  stringify: 'STRINGIFY'
}
JSON.stringify(obj, ['parse', 'stringify'])
// '{"parse":"PARSE","stringify":"STRINGIFY"}'
  • 如果是一个函数,被序列化的值的每个属性都会经过该函数的转换和处理;

处理过程:

  • 函数有两个参数,属性名(key)和属性值(value),都会被序列化;
  • 第一次调用时,key为空字符串,value则为需要序列化的整个对象;
  • 第二次处理时,会把第一次的的结果传过来,后续的每一次的处理都将接收上一次处理的结果;
  • 后面,将依次处理每个属性名和属性值,完成后返回。
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的类型处理:

  • 如果返回基本类型字符串、数字、布尔值、null,则直接被添加到序列化后的JSON字符串中;
  • 如果返回其他对象,则会在后续依次序列化该对象的属性,如果是函数则不作处理;
  • 如果返回或undefined,则不会输出该属性。
  • 序列化数组时,如果value返回undefined或者一个函数,将会被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"}'

下面示例,是返回对象值时的处理:

JSON.stringify({ json: 1, stringify: 'rr' }, (key, value) => {
  if (typeof value === 'object') { // 第一次返回整个对象时,类型是object
    return { parse: 'dd' }
  }
  return value
}) 
'{"parse":"dd"}'

space 参数

space 参数用来控制结果字符串里面的间距,美化输出。可以输入的值有以下三种情况:

  • 如果是一个数字, 序列化时,每一层级比上一层级多缩进对应数字值的空格,范围在 1 - 10,即最小1个最大10个空格;
  • 如果是一个字符串,序列化时,该字符串会添加在每行前面,每一层级比上一层级多缩进该字符串,最多是个字符,超过则截取字符串;
  • 如果是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 特性

  • 基本类型值字符串、数字、布尔值,以及String、Boolean、Number对象值,都会转成原始值字符串输出。
JSON.stringify(333) // '333'
JSON.stringify(true) // 'true'
JSON.stringify(new String('333')) //'"333"'
JSON.stringify(Boolean(true)) // 'true'
  • 基本类型的字符串,转换结果会带双引号。

    因为在还原时,双引号会让JavaScript知道是字符串,而不是变量。

JSON.stringify('json') === 'json' // false
JSON.stringify('json') === '"json"' // true
  • undefined、函数、symbol以及XML对象:
  • 出现在Object对象中时,会被忽略;
  • 出现在数组中时,会被序列化成null;
  • 单独出现时,会返回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,都会被序列化成null。
JSON.stringify(null) // 'null'
JSON.stringify(NaN) // 'null'
  • Object对象,以及Map/Set/WeakMap/WeakSet等复合类型对象,序列化时会忽略对象的不可遍历属性。
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}) // '{}'
  • 除了数组,其他对象的属性在序列化时,顺序可能会乱。
const a = { '1': 911, 'r': 822, '11': 9922}
JSON.stringify(a)
// '{"1":911,"11":9922,"r":822}'
  • 转换的对象如果定义了 toJSON() 方法,则该方法的返回值就是转换对象的序列化结果。

    该过程会忽略其他属性。

const a = { key: 'json' }
a.toJSON = () => 'JSON'
JSON.stringify(a)
// '"JSON"'
  • RegExp对象、Error对象都会序列化为空对象字符串。
JSON.stringify(/\d/) // "{}"
JSON.stringify(new Error())  // "{}"

想要序列化相应对象,需要设置实现toJSON方法才行。

RegExp.prototype.toJSON = RegExp.prototype.toString
JSON.stringify(/\d/) // '"/\\\\d/"'
  • Date对象已经定义了toJSON(),并将其转换为string字符串,因此可被序列化。

    Date.toISOString()

JSON.stringify(new Date())
// '"2021-12-31T02:24:05.477Z"'
  • 循环引用的对象执行此方法,会抛出错误。

    对象之间相互引用,形成无限循环。

const a = {}
a.key = a
JSON.stringify(a)
// Uncaught TypeError: Converting circular structure to JSON
  • 转换BigInt类型的值会抛出TypeError错误。

    BigInt值不能JSON序列化

JSON.stringify(12n)
// Uncaught TypeError: Do not know how to serialize a BigInt
  • 更好的支持unicode转义符
const a = {'\u0066': 333}
JSON.stringify(a)
// '{"f":333}'

到此这篇关于详解JSON.parse和JSON.stringify用法的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
js点击button按钮跳转到另一个新页面
Oct 10 Javascript
AngularJS入门教程之学习环境搭建
Dec 06 Javascript
JS返回iframe中frameBorder属性值的方法
Apr 01 Javascript
jquery+css3实现网页背景花瓣随机飘落特效
Aug 17 Javascript
如何根据百度地图计算出两地之间的驾驶距离(两种语言js和C#)
Oct 29 Javascript
Jquery ajax加载等待执行结束再继续执行下面代码操作
Nov 24 Javascript
使用EVAL处理jqchart jquery 折线图返回数据无效的解决办法
Nov 26 Javascript
jQuery事件的绑定、触发、及监听方法简单说明
May 10 Javascript
jQuery的extend方法【三种】
Dec 14 Javascript
JS实现简单抖动效果
Jun 01 Javascript
vue2.0项目实现路由跳转的方法详解
Jun 21 Javascript
详解如何在webpack中做预渲染降低首屏空白时间
Aug 22 Javascript
前端vue+express实现文件的上传下载示例
详解JavaScript的计时器和按钮效果设置
一篇文章告诉你如何实现Vue前端分页和后端分页
javascript的var与let,const之间的区别详解
Feb 18 #Javascript
交互式可视化js库gojs使用介绍及技巧
gojs实现蚂蚁线动画效果
uni-app 微信小程序授权登录的实现步骤
Feb 18 #Javascript
You might like
微信公众平台开发之天气预报功能
2015/08/31 PHP
PHP简单实现无限级分类的方法
2016/05/13 PHP
PHP简单读取PDF页数的实现方法
2016/07/21 PHP
PHP实现找出链表中环的入口节点
2018/01/16 PHP
jQuery操作 input type=checkbox的实现代码
2012/06/14 Javascript
Jquery动态更改一张位图的src与Attr的使用
2013/07/31 Javascript
Node.js与PHP、Python的字符处理性能对比
2014/07/06 Javascript
JavaScript判断是否为数字的4种方法及效率比较
2015/04/01 Javascript
js小数运算出现多位小数如何解决
2015/10/08 Javascript
jQuery插件cxSelect多级联动下拉菜单实例解析
2016/06/24 Javascript
JavaScript 节流函数 Throttle 详解
2016/07/04 Javascript
js将字符串中的每一个单词的首字母变为大写其余均为小写
2017/01/05 Javascript
Js自动截取字符串长度,添加省略号(……)的实现方法
2017/03/06 Javascript
判断div滑动到底部的scroll实例代码
2017/11/15 Javascript
完美解决手机浏览器顶部下拉出现网页源或刷新的问题
2017/11/30 Javascript
微信小程序动画(Animation)的实现及执行步骤
2018/10/28 Javascript
jQuery访问json文件中数据的方法示例
2019/01/28 jQuery
VUE解决 v-html不能触发点击事件的问题
2019/10/28 Javascript
解决vuex数据页面刷新后初始化操作
2020/07/26 Javascript
python实现隐马尔科夫模型HMM
2018/03/25 Python
python dataframe常见操作方法:实现取行、列、切片、统计特征值
2018/06/09 Python
selenium+python实现1688网站验证码图片的截取功能
2018/08/14 Python
selenium+python自动化测试之鼠标和键盘事件
2019/01/23 Python
python实现抖音点赞功能
2019/04/07 Python
python对象与json相互转换的方法
2019/05/07 Python
基于Python 中函数的 收集参数 机制
2019/12/21 Python
pyecharts调整图例与各板块的位置间距实例
2020/05/16 Python
python文件操作seek()偏移量,读取指正到指定位置操作
2020/07/05 Python
英国复古服装购物网站:Collectif
2019/10/30 全球购物
Vrbo英国:预订度假屋
2020/08/19 全球购物
计算机毕业大学生推荐信
2013/12/01 职场文书
校园学雷锋活动月总结
2014/03/09 职场文书
12.4全国法制宣传日活动方案
2014/11/02 职场文书
三年级学生期末评语
2014/12/26 职场文书
观看《筑梦中国》纪录片心得体会
2016/01/18 职场文书
对讲机知识
2022/04/07 无线电