JavaScript 中的 JSON

198 阅读4分钟

JSON是一种数据格式,JSON 并不从属于 JavaScript,很多编程语言都有针对 JSON 的解析器和序列化器。

语法

  • 简单值:在 JSON 中表示字符串、数值、布尔值和 null,但不支持 JavaScript 中的特殊值 undefined。
 // JSON字符串必须使用双引号
"Hello World"
  • 对象:表示的是一组无序的键值对,属性的值可以是简单值,也可以是复杂类型值。
// JSON 中的对象要求必须给属性加双引号
{
  "name": "Nicholas", 
  "age": 29
}
  • 数组:表示一组有序的值的列表。
[{
  "title": "Professional JavaScript",
  "authors": ["Nicholas C. Zakas"],
  "edition": 3,
  "year": 2011
},{
  "title": "Professional JavaScript",
  "authors": ["Nicholas C. Zakas"],
  "edition": 2,
  "year": 2009
}]

解析与序列化

JSON 数据结构解析为有用的 JavaScript 对象。

JSON对象

JSON 对象有两个方法:stringify()和 parse()。

JSON.stringify()  // 把 JavaScript 对象序列化为 JSON 字符串,默认情况输出的 JSON 字符串不包含任何空格字符或缩进
JSON.parse()  // 把 JSON 字符串解析为原生 JavaScript 值

序列化选项

JSON.stringify()除了要序列化的 JavaScript对象外,还可以接收另外两个参数,这两 个参数用于指定以不同的方式来序列化 JavaScript 对象。

JSON.stringify(param1, param2, param3) 
// param1: javascript值 
// param2: 见过滤结果
// param3: 见字符串缩进
  • 过滤结果
// param2:第二个参数是数组
// 一个数组包含对象属性,在返回的结果字符串中,就只会包含定义的属性

var jsonObj = [{
  "title": "Professional JavaScript",
  "authors": ["Nicholas C. Zakas"],
  "edition": 3,
  "year": 2011
},{
  "title": "Professional JavaScript",
  "authors": ["Nicholas C. Zakas"],
  "edition": 2,
  "year": 2009
}]
var jsonText = JSON.stringify(jsonObj, ["title", "year"])
jsonText // "[{"title":"Professional JavaScript","year":2011},{"title":"Professional JavaScript","year":2009}]"
// param2:第二个参数是函数
// 传入的函数接收两个参数,属性(键)名和属性值。
// 属性名只能是字符串,而在值并非键值对儿结构的值时,键名可以是空字符串。
// 如果函数返回了undefined,那么相应的属性会被忽略。

var book = {
  title: 'Professional JavaScript',
  authors: ['Nicholas C. Zakas', 'Bob'],
  edition: 3,
  year: 2011
}
var bookStr = JSON.stringify(book, function(key, value) {
  if (key === "authors") {
    return value.join(",")
  } else if (key === "year" || key === "edition") {
	return undefined
  } else {
    return value
  }
})
bookStr  // "{"title":"Professional JavaScript","authors":"Nicholas C. Zakas,Bob"}"
  • 字符串缩进
// parma3:第三个参数
// 如果这个参数是一个数值,那它表示的是每个级别缩进的空格数,并且字符串中插入了换行符以提高可读性。
var book = {
  title: 'Professional JavaScript',
  authors: ['Nicholas C. Zakas', 'Bob'],
  edition: 3,
  year: 2011
}
var jsonText = JSON.stringify(book, null, 4)
/** jsonText result
"{
    "title": "Professional JavaScript",
    "authors": [
        "Nicholas C. Zakas",
        "Bob"
    ],
    "edition": 3,
    "year": 2011
}"
*/
// parma3:第三个参数
// 如果这个参数是一个字符串,这个字符串将在 JSON 字符串中被用作缩进字符。
// 并且字符串中插入了换行符以提高可读性。
var book = {
  title: 'Professional JavaScript',
  authors: ['Nicholas C. Zakas', 'Bob'],
  edition: 3,
  year: 2011
}
var jsonText = JSON.stringify(book, null, '-')
/** jsonText result
"{
-"title": "Professional JavaScript",
-"authors": [
--"Nicholas C. Zakas",
--"Bob"
-],
-"edition": 3,
-"year": 2011
}"
*/
  • toJSON()方法
    可以为任何对象添加 toJSON()方法,用来作为函数过滤器的补充。
var book = {
  title: 'Professional JavaScript',
  authors: ['Nicholas C. Zakas', 'Bob'],
  edition: 3,
  year: 2011,
  toJSON: function () {
    return {
      title: this.title
    }
  }
}
JSON.stringify(book)  // "{"title":"Professional JavaScript"}"

把一个对象传 入 JSON.stringify(),序列化该对象的顺序如:

  1. 如果存在 toJSON()方法而且能通过它取得有效的值,则调用该方法。否则,返回对象本身。
  2. 如果提供了第二个参数,应用这个函数过滤器。传入函数过滤器的值是第(1)步返回的值。
  3. 对第(2)步返回的每个值进行相应的序列化。
  4. 如果提供了第三个参数,执行相应的格式化。

解析选项

JSON.parse(param1, parma2)
// param1: JSON格式字符串
// param2: 还原函数,接收两个参数,一个键和一个值,并且要返回一个值

var book = {
  title: 'Professional JavaScript',
  year: 2011,
  releaseDate: new Date(2011, 11, 1)
}

var jsonText = JSON.stringify(book);  // "{"title":"Professional JavaScript","year":2011,"releaseDate":"2011-11-30T16:00:00.000Z"}"

var bookCopy = JSON.parse(jsonText, function(key, value){
  if (key == "releaseDate"){
    return new Date(value);
  } else {
    return value;
  }
})
/** bookCopy result
{
  releaseDate: Thu Dec 01 2011 00:00:00 GMT+0800 (CST),
  title: "Professional JavaScript",
  year: 2011
}
*/

兼容性

原生的 JSON 对象也得到了很多浏览器的支持,比如 IE8+、Firefox 3.5+、Safari 4+、Opera 10.5 和 Chrome。
对于不能支持原生json的浏览器可使用:https://github.com/douglascrockford/JSON-js