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

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

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

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

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函数,属性名和值作为参数两个参数 keyvalue 传入。

    遍历顺序:按照层级,从内往外遍历,最终到达最顶层,则是解析值本身。
  • reviver返回undefined,则删除该对象,如果返回了其他值,则该值会成为当前属性的新值。
  • 当遍历到最顶层时,因为没有属性了,参数key是空字符串'',参数value则是当前解析值。

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

  • 基本值类型数据(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数据对值的类型和格式,都有严格的规定,具体的规则如下:

  1. 该方法使用字符串类型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
  1. 字符串必须使用双引号,不能使用单引号。
JSON.parse('"String"')
// 'String'
JSON.parse('\'String\'')
// Uncaught SyntaxError: Unexpected token ' in JSON at position 0
  1. 只支持十进制的字符串,但小数点后必须跟上数字。
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
  1. 不能使用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
  1. 复合类型,只能是:[]{} 这样的字面量。

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

    不能使用Object和Array,也不能是函数、RegExp对象、Date对象、Error对象等。
JSON.parse('[]')
// []
JSON.parse('Object()')
// Uncaught SyntaxError: Unexpected token O in JSON at position 0
  1. 对象的属性名必须使用双引号。
JSON.parse('{"key": 1 }')
// {key: 1}
JSON.parse('{key: 1 }')
// Uncaught SyntaxError: Unexpected token k in JSON at position 1
  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
  1. 支持unicode转义。
JSON.parse('{"\u0066":333}')
// {f: 333}
  1. 部分控制字符、转义字符不支持,如'\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 参数可以以下三种情况:

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

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

处理过程:

  • 函数有两个参数,属性名(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 特性

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

    因为在还原时,双引号会让JavaScript知道是字符串,而不是变量。
JSON.stringify('json') === 'json' // false
JSON.stringify('json') === '"json"' // true
  1. 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 }) // '{}'
  1. NaN、Infinity和-Infinity等值,还有null,都会被序列化成null。
JSON.stringify(null) // 'null'
JSON.stringify(NaN) // 'null'
  1. 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"}'
  1. 以symbol为属性名的属性将被忽略。
JSON.stringify({[Symbol()]: 333}) // '{}'
  1. 除了数组,其他对象的属性在序列化时,顺序可能会乱。
const a = { '1': 911, 'r': 822, '11': 9922}
JSON.stringify(a)
// '{"1":911,"11":9922,"r":822}'
  1. 转换的对象如果定义了 toJSON() 方法,则该方法的返回值就是转换对象的序列化结果。

    该过程会忽略其他属性。
const a = { key: 'json' }
a.toJSON = () => 'JSON'
JSON.stringify(a)
// '"JSON"'
  1. RegExp对象、Error对象都会序列化为空对象字符串。
JSON.stringify(/\d/) // "{}"
JSON.stringify(new Error()) // "{}"

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

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

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

    对象之间相互引用,形成无限循环。
const a = {}
a.key = a
JSON.stringify(a)
// Uncaught TypeError: Converting circular structure to JSON
  1. 转换BigInt类型的值会抛出TypeError错误。

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

JSON.parse 和 JSON.stringify 详解的更多相关文章

  1. JSON.parse和JSON.stringify 参数详解

    JSON.parse和JSON.stringify这两个浏览器自带(IE6/7除外)的方法平常我们经常用到,但是一般都只是用到了他们的第一个参数,比如字符串转对象:JSON.parse('{}')   ...

  2. JSON.parse()与JSON.stringify()和eval()使用方法详解

    在和后端对接口的时候,遇到了一个问题 就是series里面数据变量进行拼接的时候,data数据里面全部是数值int类型的 但是因为某些需求需要让他进行某个数据之前的数据都为空 我试过用空字符串和und ...

  3. JSON.parse() 和 JSON.stringify()

    JSON.parse()和JSON.stringify()   1.parse 用于从一个字符串中解析出json 对象.例如 var str='{"name":"cpf& ...

  4. arguments.callee 调用函数自身用法----JSON.parse()和JSON.stringify()前端js数据转换json格式

    arguments.callee 调用函数自身用法 arguments.callee 在哪一个函数中运行,它就代表哪个函数. 一般用在匿名函数中. 在匿名函数中有时会需要自己调用自己,但是由于是匿名函 ...

  5. 有关javascript中的JSON.parse和JSON.stringify的使用一二

    有没有想过,当我们的大后台只是扮演一个数据库的角色,json在前后台的数据交换中扮演极其重要的角色时,作为依托node的前端开发,其实相当多的时间都是在处理数据,准确地说就是在处理逻辑和数据(这周实习 ...

  6. Jquery里面种的 JSON.parse() 与JSON.stringify() 的区别

    JSON.parse()与JSON.stringify()的区别   JSON.parse()[从一个字符串中解析出json对象] Demo: //定义一个字符串 var data='{"N ...

  7. JSON.parse()和JSON.stringify()的解析与用途

    JSON.parse()和JSON.stringify()的解析与用途 1.parse用于从一个字符串中解析出json对象 如: var str = '{"name":" ...

  8. JSON.parse() 和 JSON.stringify() 的区别

    JSON.parse()与JSON.stringify()的区别   JSON.parse()[从一个字符串中解析出json对象] //定义一个字符串 var data='{"name&qu ...

  9. 秒懂JSON.parse()与JSON.stringify()的区别

    在网站开发中,Json是最为常见的一种数据交互手段.在使用过程中,常会遇到Json字段串和对象之间进行转换.很多朋友对于JSON.parse() 和JSON.stringify() 的区别,下面为大家 ...

随机推荐

  1. Spark(四)【RDD编程算子】

    目录 测试准备 一.Value类型转换算子 map(func) mapPartitions(func) mapPartitions和map的区别 mapPartitionsWithIndex(func ...

  2. Zookeeper【概述、安装、原理、使用】

    目录 第1章 Zookeeper入门 1.1 概述 1.2 特点 1.3 数据结构 1.4应用场景 第2章 Zookeep安装 2.1 下载地址 2.2 本地模式安装 1. 安装前准备 2. 配置修改 ...

  3. map和forEach的区别

    总结 forEach()可以做到的东西,map()也同样可以.反过来也是如此. map()会分配内存空间存储新数组并返回,forEach()不会返回数据. forEach()允许callback更改原 ...

  4. 【Java 8】 集合间转换工具——Stream.collect

    集合运算 交集 (list1 + list2) List<T> intersect = list1.stream() .filter(list2::contains) .collect(C ...

  5. 图的存储(Java)以及遍历

    // 深搜 private void dfs(int v) { visited[v] = true; System.out.print(v+" "); for (int i = 0 ...

  6. maven 是什么?

    在了解maven的概念之前,我一直都在项目中使用maven,但是对于maven的了解,只能说连个皮毛都算不上,一直到项目中,自己机械化的deploy项目的时候,发现报错,赶紧报告开发组长,这私服是不是 ...

  7. 【Java基础】Java中new对象的过程

    序言 联系我上次写的关于Java内存的文章,对象访问在 Java 语言中无处不在,是最普通的程序行为,但即使是最简单的访问,也会却涉及 Java 栈.Java 堆.方法区这三个最重要内存区域之间的关联 ...

  8. 云原生时代之Kubernetes容器编排初步探索及部署、使用实战-v1.22

    概述 **本人博客网站 **IT小神 www.itxiaoshen.com Kubernetes官网地址 https://kubernetes.io Kubernetes GitHub源码地址 htt ...

  9. Mysql资料 mysqldump

    目录 一.简介 备份过程 优缺点 命令使用 myisam引擎 二.安装 配置 日志 三.日常使用 备份全库 备份单个库(带建立库的语句) 备份单个库(不自动建立库) 备份表合集 从全备中恢复单个库 其 ...

  10. 跨平台调用之WebService

    一.简介 web service是一种跨编程语言和跨操作系统平台的远程调用技术,是基于网络的.分布式的模块化组件. 跨编程语言就是说服务器端程序采用 Java 编写,客户端程序则可以采用其他编程语言编 ...