JSON

作者: 一蓑烟雨任平生_cui | 来源:发表于2019-05-29 15:48 被阅读0次

JSON格式是一种轻量级的用于数据交换的文本格式,不是一种编程语言。

优点:简洁清晰,符合js语法,可以由js引擎直接处理。

JSON对象

JSON对象包含两个方法: 用于解析JSON的parse()方法以及将对象/值转换为 JSON字符串的 stringify() 方法。除了这两个方法, JSON这个对象本身并没有其他作用,也不能被调用或者作为构造函数调用。

早期JSON解析器基本上使用eval()函数,使用eval()存在风险,可能会执行恶意代码。ES5定义了全局JSON对象,提供了两个静态方法JSON.stringify() 和 JSON.parse();对于较老版本的浏览器还需要使用shim。

JSON流行还有更重要的一点是可以把JSON数据结构解析成javascript对象,与XML要解析成DOM文档从中提取数据极为繁琐相比,JSON简洁清晰的优势就极其明显。

JSON中的对象和javascript对象字面量的区别:

  1. 没有声明变量,即JSON中没有变量的概念
  2. 末尾没有分号(因为不是javascript语句)
  3. 对象的属性必须加双引号

可表示的值类型

  1. 原始类型:
* 字符串、数字(必须是十进制)、null、布尔值
* 不能使用NaN, Infinity, -Infinity和undefined
  1. 复杂类型
* 数组或对象,不能是函数、正则表达式对象、日期对象(因为日期对象有toJSON()方法,下面具体介绍)

格式

  1. 字符串必须用双引号表示,不能使用单引号
  2. 对象的key必须用双引号表示
  3. 对象或数组的最后一个成员不可加逗号

序列化方法 JSON.stringify()

1. 参数一:要序列化的值

JSON.stringify()方法用于将一个值转为 JSON 字符串。

JSON.stringify(122)     // "122"
JSON.stringify(false)   // "false"
JSON.stringify(null)    // "null"
JSON.stringify('sina')  // ""sina""
JSON.stringify([])      // "[]"
JSON.stringify({})      // "{}"

对于字符串,转换结果会带双引号

JSON.stringify('sina') === "\"sina\""  // true

对象的属性如果是函数、undefined、XML对象,以及原型成员、不可枚举属性,会被JSON.stringify()过滤。

JSON.stringify({name: undefined})            // "{}"
JSON.stringify({ skill: function() {} })     // "{}"
JSON.stringify([ undefined, function() {} ]) // "[]"
JSON.stringify(/sina/)                       // "{}"

const obj = { age: 12 }

Object.defineProperty(obj, 'name', {
  value: 'jack',
  enumerable: false
})

JSON.stringify(obj)        // "{"age": 12}"
2. 参数二:过滤器

JSON.stringify()还可以接受第二个参数作为过滤器,该参数可以是数组或函数。

  1. 如果是数组,则JSON.stringify()的结果中将只包含数组中列出的属性,该方式只对对象有效,对数组无效。
const obj {
  name: 'jack',
  age: 12,
  address: 'sina'
}
JSON.stringify(obj, ['name', 'address']) // "{"name": "jack", "address": "sina"}"

JSON.stringify([1,2,3], [1]) // "[1,2,3]"
  1. 如果是函数,该函数接收两个参数,key、value,根据key来处理要序列化的对象中的属性值。
const obj {
  a: 1,
  b: 2,
  c: 'sina'
}
JSON.stringify(obj, (key, value) => {
  if (typeof key === 'number') return value * 3
  return value
})

// "{"a": 3, "b": 6, "c": "sina"}"

需要注意的是,该处理函数会递归所有的key,如:

const obj = {
  a: 2,
  b: {
    c: 3
  }
}
JSON.stringify(obj, (key, value) => {
  console.log('key: ', key, ' ; value: ', value)
  if (typeof key === 'number') return value * 2
  return value
})
// key:  '' ; value:  {a: 2, b: {c: 3}}
// key:  a  ; value:  2
// key:  b  ; value:  {c: 3}
// key:  c  ; value:  3

// "{"a":2,"b":{"c":3}}"

以上执行结果,函数被处理了四次,最后是执行结果。 第一次key为空,value是整个对象;第二次key为a,value为2;第三次key为b,value为{c: 3};第四次key为c,value为3。

递归处理中每一次处理的对象,都是前一次返回的值

const obj = {
  a: {
    b: 2
  },
  c: 4
}

JSON.stringify(obj, (key, value) => {
  if (key === 'a') return {b: 22}
  if (typeof value === 'number') return value * 2
  return value
})

// "{"a":{"b":44},"c":8}"

如果函数返回undefined,则该属性会被忽略。

const obj = {name: 'jack', age: 12}
JSON.stringify(obj, (key, value) => {
  if (typeof value === 'number') return undefined
  return value
})

// "{"name": "jack"}"
3. 参数三:字符串缩进

JSON.stringify() 的第三个参数用于控制结果中的缩进和空白符。如果参数是数值,则表示每个级别缩进的空格数。最大缩进10个。还可以是字符串,最长不超过10个字符。

JSON.stringify({age: 12}, null, 2)
"{
  "age": 12
}"

JSON.stringify({age: 12}, null, '--')
"{
--"age": 12
}"

toJSON() 方法

有时候JSON.stringify()还不能满足对某些对象进行自定义序列化的需求。在这种情况下可以给对象添加toJSON()方法,返回自定义的数据,忽略对象的其他参数,然后再序列化。原生Date对象有一个toJSON()方法,能够将javascript中的Date对象自动转成ISO 8610日期字符串(与Date对象上调用toString()结果完全一样)

JSON.stringify({
  a: 1,
  toJSON() {
    return {b: 2}
  }
})
//  "{"b":2}"

JSON.stringify({date: new Date()}) // "{"date":"2019-05-29T07:14:15.035Z"}"

toJSON()的一个应用场景是将正则对象转字符串

RegExp.prototype.toJSON = RegExp.prototype.toString
JSON.stringify(/sina/) // ""/sina/""

解析选项JSON.parse()

JSON.parse() 可以接收另外一个参数,该参数是一个函数,将在每个键值对上调用,与JSON.stringify()过滤器对应,该函数被称为还原函数

如果还原函数返回undefined,则表示将该属性从结果中删除;如果返回其他值,则插入结果中。

在将日期字符串还原时会经常用到还原函数。

const obj = {
  date: new Date(),
  a: 12,
  name: 'jack',
  address: 'sina'
}

const jsonText = JSON.stringify(obj)
JSON.parse(jsonText, (key, value) => {
  if (key === 'date') return new Date(value)
  if (typeof value === 'number') return value * 2
  if (key === 'address') return undefined
  return value
})

/*
{
  a: 24,
  date: Wed May 29 2019 15:36:14 GMT+0800 (中国标准时间),
  name: "jack"
}
/*

如果传入的字符串不是有效的 JSON 格式,JSON.parse方法将报错。可以将JSON.parse方法放在try...catch代码块中,处理解析错误。

JSON.parse("\"sina\"")  // "sina"
JSON.parse('"sina"')    // "sina"
JSON.parse("23423")     // 23423
try {
  JSON.parse("'sian'")
}
catch(e) {
  console.log('error')
}

参考:
高级程序设计
MDN

相关文章

网友评论

      本文标题:JSON

      本文链接:https://www.haomeiwen.com/subject/qmuytctx.html