详解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 相关文章推荐
JavaScript面向对象知识串结(读JavaScript高级程序设计(第三版))
Jul 17 Javascript
利用javascript判断文件是否存在
Dec 31 Javascript
js中使用replace方法完成某个字符的转换
Aug 20 Javascript
跟我学习javascript的Date对象
Nov 19 Javascript
JavaScript实战之带收放动画效果的导航菜单
Aug 16 Javascript
Vue.js第一天学习笔记(数据的双向绑定、常用指令)
Dec 01 Javascript
基于JS实现移动端向左滑动出现删除按钮功能
Feb 22 Javascript
jQuery tip提示插件(实例分享)
Apr 28 jQuery
Node.js 的模块知识汇总
Aug 16 Javascript
vue+swiper实现组件化开发的实例代码
Oct 26 Javascript
详解vue 不同环境配置不同的打包命令
Apr 07 Javascript
vue el-table实现递归嵌套的示例代码
Aug 14 Vue.js
前端vue+express实现文件的上传下载示例
详解JavaScript的计时器和按钮效果设置
一篇文章告诉你如何实现Vue前端分页和后端分页
javascript的var与let,const之间的区别详解
Feb 18 #Javascript
交互式可视化js库gojs使用介绍及技巧
gojs实现蚂蚁线动画效果
uni-app 微信小程序授权登录的实现步骤
Feb 18 #Javascript
You might like
PHP资源管理框架Assetic简介
2014/06/12 PHP
php根据日期或时间戳获取星座信息和生肖等信息
2015/10/20 PHP
ECshop 迁移到 PHP7版本时遇到的兼容性问题
2016/02/15 PHP
php实现的错误处理封装类实例
2017/06/20 PHP
Code:loadScript( )加载js的功能函数
2007/02/02 Javascript
json原理分析及实例介绍
2012/11/29 Javascript
jQuery的Ajax的自动完成功能控件简要说明
2013/02/22 Javascript
使用jquery动态加载js文件的方法
2014/12/24 Javascript
jQuery随机密码生成的方法
2015/03/09 Javascript
JQuery中DOM事件冒泡实例分析
2015/06/13 Javascript
js实现类似MSN提示的页面效果代码分享
2015/08/24 Javascript
JavaScript tab选项卡插件实例代码
2016/02/23 Javascript
jQuery实现无限往下滚动效果代码
2016/04/16 Javascript
JS实现求数组起始项到终止项之和的方法【基于数组扩展函数】
2017/06/13 Javascript
Node.js中 __dirname 的使用介绍
2017/06/19 Javascript
用Vue.extend构建消息提示组件的方法实例
2017/08/08 Javascript
微信小程序实现聊天对话(文本、图片)功能
2018/07/06 Javascript
jQuery删除/清空指定元素的所有子节点实例代码
2019/07/04 jQuery
微信小程序单选框自定义赋值
2020/05/26 Javascript
JS实现电脑虚拟键盘打字测试
2020/06/24 Javascript
解决vuex改变了state的值,但是页面没有更新的问题
2020/11/12 Javascript
[00:32]2018DOTA2亚洲邀请赛Liquid出场
2018/04/03 DOTA
python skimage 连通性区域检测方法
2018/06/21 Python
Python实现计算对象的内存大小示例
2019/07/10 Python
Django Rest framework解析器和渲染器详解
2019/07/25 Python
python  ceiling divide 除法向上取整(或小数向上取整)的实例
2019/12/27 Python
pyspark 随机森林的实现
2020/04/24 Python
Python爬虫爬取博客实现可视化过程解析
2020/06/29 Python
iHerb台湾:维生素、保健品和健康产品
2018/01/31 全球购物
介绍一下UNIX启动过程
2013/11/14 面试题
毕业生就业自荐信
2013/12/04 职场文书
2014年党的群众路线学习心得体会
2014/11/05 职场文书
介绍信范文
2015/01/31 职场文书
2015年求职自荐信范文
2015/03/04 职场文书
python spilt()分隔字符串的实现示例
2021/05/21 Python
分析SQL窗口函数之排名窗口函数
2022/04/21 Oracle