学习笔记——JSON数据格式

231 阅读5分钟

记录在红宝石书上看到关于JSON的知识

JSON是一种数据格式,不是一种编程语言

JSON的语法可以表示以下三种类型的值:

  1. 简单值:字符串、数值、布尔值和null。但JSON不支持JavaScript中的特殊值undefined

    例如:JSON表示字符串的方式:"Hello world!";JSON表示数组为 666 的方式:666

  2. 对象:对象作为一种复杂数据类型,表示的是一组无序的键值对。而每个键值对中的值可以是简单值,也可以是复杂数据类型的值

    例如:JSON表示对象的方式:
    {
      "name": "Mashy",
      "age": 24,
      "hobby": [ "Music", "football" ]
    }

  3. 数组:数组也是一种复杂数据类型,表示的是一组有序的值的列表,可以通过数值索引来访问其中的值。数组的值也可以是任意类型——简单值、对象和数组

    例如:JSON表示对象的方式:
    [
      {
        "name": "zhangsan",
        "age": 22,
        "hobby": [ "Music", "football" ]
      },  
      {
        "name": "lisi",
        "age": 25,
        "hobby": [ "Music", "football" ]
      }
    ]

注意:

  • JSON字符串必须使用双引号(单引号会导致语法错误)
  • JSON对象的属性必须使用双引号
  • 同一个对象中绝对不应该出现两个同名的属性

JSON序列化和解析

JSON对象有两个方法(ECMAScript 5):

  • stringify():将JavaScript对象序列化为JSON字符串
  • parse():将JSON字符串解析为原生JavaScript值

JSON序列化:stringify()

该方法接受三个参数:

  • 要序列化的JavaScript对象
  • 过滤器(可以是一个数组,也可以是一个函数)
  • 选项(表示是否在JSON字符串中保留缩进)
注意:后两个参数是用于指定以不同的方式序列化JavaScript对象

第一个参数:要序列化的JavaScript对象(结合到第二、第三个参数中)

第二个参数:过滤器(可以是一个数组,也可以是一个函数)

假如第二个参数是数组,那么JSON.stringify()的结果中将包含数组中列出的属性。

例如:返回标题和年份
var book1= {
    "title": "书名",
    "authors": ["zhangsan", "lisi"],
    "edition": 1,
    "year": 2020
}
var jsonText1 = JSON.stringify(book1, ["title","year"]);
console.log(jsonText1);    // "{"title":"书名","year":2020}"

假如第二个参数是函数,传入的函数接受两个参数:属性(键)名和属性值。

注意:属性(键)名只能是字符串。

例如:将作者名用 "," 分隔开,年份改为 2021,删除属性 "edition",其他不变
var jsonText2 = JSON.stringify(book1, function(key, value){    switch(key){
            case "authors":
                return value.join(",");
            case "year":
                return 2021;
            case "edition":
                return undefined;    // 通过返回undefined,删除该属性
            default:    // 一定要提供default项返回传入的值,以便其他值能正常出现在结果中
                return value;
    }
});
console.log(jsonText2);    // "{"title":"书名","authors":"zhangsan,lisi","year":2021}"

第三个参数:选项(表示是否在JSON字符串中保留缩进)

作用:控制结果中的缩进和空白符(最大缩进长度为10,超过10个则只出现前10个)

如果第三个参数是数值,则表示每个级别缩进的空格数

例如:要在每个级别缩进6个空格
var jsonText3 = JSON.stringify(book1, null, 6);
console.log(jsonText3)
输出:
"{
      "title": "书名",
      "authors": [
            "zhangsan",
            "lisi"
      ],
      "edition": 1,
      "year": 2020
}"

如果第三个参数是一个字符串,则这个字符串将在JSON字符串中被用作缩进字符(不再使用空格缩进)

例如:使用字符串 "#_#" 缩进JSON字符串
var jsonText4 = JSON.stringify(book1, null, "#_#");
console.log(jsonText4)
输出:
"{
#_#"title": "书名",
#_#"authors": [
#_##_#"zhangsan",
#_##_#"lisi"
#_#],
#_#"edition": 1,
#_#"year": 2020
}"

另外,JSON.stringify()有时不能满足对某些对象进行自定义序列化的需求。在这些情况下,可以给对象定义toJSON()方法,反馈其自身的JSON数据格式。

可以给任意对象添加toJSON()方法:
var book2= {
    "title": "书名",
    "authors": ["zhangsan", "lisi"],
    "edition": 1,
    "year": 2020,
    toJSON: function(){
        return this.title;
    }
}
var jsonText5 = JSON.stringify(book2)
// 序列化之后,执行toJSON()方法返回相应数据
console.log(jsonText5)    // ""书名""
注意:toJSON()方法作为函数过滤器的补充。

总结:假如将一个对象传入JSON.stringify(),序列化该对象的顺序如下:

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

JSON解析选项:parse()

该方法接受两个参数:

  • 要序列化的JavaScript对象
  • 函数(在每个键值对上调用)

第一个参数:要序列化的JavaScript对象(结合到第二中)

第二个参数:函数

该函数接受两个参数:键和值。而且都需要返回一个值。

例如:将对象book3中的标题 "书名" 改为 "书名改变了",其他不变
var book3= {
    "title": "书名",
    "authors": ["zhangsan", "lisi"],
    "edition": 1,
    "year": 2020
}

// 序列化
var jsontext6 = JSON.stringify(book3)
console.log(jsontext6)
//  "{"title":"书名","authors":["zhangsan","lisi"],"edition":1,"year":2020}"

var changeBookTitle = JSON.parse(jsontext6,function(key, value){
    if(key === 'title'){
        return "书名改变了";
    }else{
        return value;
    }
})
console.log(JSON.stringify(changeBookTitle))
// "{"title":"书名改变了","authors":["zhangsan","lisi"],"edition":1,"year":2020}"

总结

ECMAScript 5定义了一个原生的JSON对象,可以用来将对象序列化为JSON字符串或者将JSON数据解析为JavaScript对象JSON.stringify()JSON.parse()方法分别用来实现上述两项功能。这两个方法都有一些选项,通过他们可以改变过滤的方式,或者改变序列化的过程。

原生的JSON对象得到了很多浏览器的支持:IE8+、Firefox 3.5+、Safari 4+、Opera 10.5 和Chrome。