0


轻量级数据格式 —— JSON

JSON

文章目录

前言 : JavaScript 对象简谱(JSON,JavaScript Object Notation)标准,JSON 是 JavaScript 的严格子集,利用 JavaScript 中的几种模式来表示结构化数据。理解 JSON 最关键的一点是要把它当成一种数据格式,而不是编程语言。JSON 不属于 JavaScript,它们只是拥有相同的语法而已。JSON也不是只能在 JavaScript 中使用,它是一种通用数据格式。很多语言都有解析序列化 JSON 的内置能力。

在这里插入图片描述

JSON 语法

支持三种类型

  • 简单值 : 字符串数值布尔值null 可以在 JSON 中出现,就像在 JavaScript 中一样。特殊值 undefined 不可以
  • 对象 : 第一种复杂数据类型,对象表示有序键/值对。每个值可以是简单值,也可以是复杂类型。
  • 数组 : 第二种复杂数据类型,数组表示可以通过数值索引访问的值的有序列表。数组的值可以是任意类型,包括简单值、对象,甚至其他数组。

注意 : JSON 没有变量、函数或对象实例的概念。JSON 的所有记号都只为表示结构化数据,虽然它借用了JavaScript 的语法,但是千万不要把它跟JavaScript 语言混淆。

简单值

  • 最简单的 JSON 可以是一个数值。 - 举个栗子 : - 5- "hello"- 布尔值null 本身也是有效的 JSON 值。

注意 : JavaScript 字符串与 JSON 字符串的主要区别是,JSON 字符串必须使用双引号(单引号会导致语法错误)

对象

  • 对象使用与 JavaScript 对象字面量略为不同的方式表示。- 以下是 JavaScript 中的对象字面量:- let object ={"name":"Nicholas","age":29};- 而 JSON 的表示对象语法是- {"name":"Nicholas","age":29}
  • JavaScript 对象字面量相比,JSON 主要有两处不同。首先,没有变量声明(JSON 中没有变量)。其次,最后没有分号(不需要,因为不是 JavaScript 语句)。同样,用引号将属性名包围起来才是有效的 JSON
  • JavaScriptJSON属性的值都可以是简单值复杂数据类型值,而JSON可以在对象中再嵌入对象。- 比如 :JSON数据- {"name":"Nicholas","age":29,"school":{"name":"Merrimack College","location":"North Andover, MA"}}- 上述例子中即使整个 JSON 对象中有两个属性都叫 “name” ,但它们属于两个不同的对象,一个是外面对象的"name"属性,另个是里面 “school” 对象的 “name” 属性,因此是允许的。同一个对象中不允许出现两个相同的属性。
  • JavaScript 不同,JSON 中的对象属性名必须始终带双引号手动编写 JSON 时漏掉这些双引号或使用单引号是常见错误。

数组

  • JSON 的第二种复杂数据类型是数组
  • 数组在 JSON 中使用 JavaScript 的数组字面量形式表示。- 例如,以下是一个 JavaScript 数组:- let values =[5,"哈喽",false];
  • 在 JSON 中可以使用类似语法表示相同的数组:- [25, "hi", true]
  • 同样,JSON没有变量,也没有分号。数组和对象可以组合使用,以表示更加复杂的数据结构- [ { "title": "Professional JavaScript", "authors": [ "Nicholas C. Zakas", "Matt Frisbie" ], "edition": 4, "year": 2017 }, { "title": "Professional JavaScript", "authors": [ "Nicholas C. Zakas" ], "edition": 3, "year": 2011 }, { "title": "Professional JavaScript", "authors": [ "Nicholas C. Zakas" ], "edition": 2, "year": 2009 }, { "title": "Professional Ajax", "authors": [ "Nicholas C. Zakas", "Jeremy McPeak", "Joe Fawcett" ], "edition": 2, "year": 2008 }, { "title": "Professional Ajax", "authors": [ "Nicholas C. Zakas", "Jeremy McPeak", "Joe Fawcett" ], "edition": 1, "year": 2007 }, { "title": "Professional JavaScript", "authors": [ "Nicholas C. Zakas" ], "edition": 1, "year": 2006 }]
  • 对象数组通常会作为 JSON 数组的顶级结构,以便创建大型复杂数据结构。

解析和序列化

JSON 的迅速流行并不仅仅因为其语法与 JavaScript 类似,很大程度上还因为 JSON 可以直接被解析成可用的 JavaScript 对象。与解析为 DOM 文档的 XML 相比,这个优势非常明显。为此,JavaScript 开发者可以非常方便地使用 JSON 数据。

比如 : JSON数据中books数组

[
    {
        "title": "Professional JavaScript",
        "authors": [
            "Nicholas C. Zakas",
            "Matt Frisbie"
        ],
        "edition": 4,
        "year": 2017
    },
    {
        "title": "Professional JavaScript",
        "authors": [
            "Nicholas C. Zakas"
        ],
        "edition": 3,
        "year": 2011
    },
    {
        "title": "Professional JavaScript",
        "authors": [
            "Nicholas C. Zakas"
        ],
        "edition": 2,
        "year": 2009
    }
]

获取第二本书的书名 :

books[1].title

JSON 对象

早期的

JSON

解析器基本上就相当于

JavaScript

的 eval() 函数。因为

JSON

JavaScript

语法的子集,所以 eval() 可以解析、解释,并将其作为

JavaScript

对象和数组返回。

  • JSON 对象在JavaScript中有两个方法 :- stringify() : 将JavaScript 序列化为 JSON 字符串- parse() : 将 JSON 解析为原生 JavaScript
  • 举个栗子 :- let book ={ title:"Professional JavaScript", authors:["Nicholas C. Zakas","Matt Frisbie"], edition:4, year:2017};//JavaScript的对象let jsonText =JSON.stringify(book);//将JavaScript对象序列化为JSON- 这个例子使用 JSON.stringify() 把一个 JavaScript 对象序列化为一个 JSON 字符串,保存在变量 jsonText 中。- 默认情况下, JSON.stringify() 会输出不包含空格或缩进的 JSON 字符串- 变量 jsonText 的内容 :- {"title":"Professional JavaScript","authors":["Nicholas C. Zakas","Matt Frisbie"],"edition":4,"year":2017}
  • 在序列化 JavaScript 对象时,所有函数和原型成员都会有意地在结果中省略。此外,值为 undefined 的任何属性也会被跳过。最终得到的就是所有实例属性均为有效 JSON 数据类型的表示。
  • JSON 字符串可以直接传给 JSON.parse(),然后得到相应的 JavaScript 值。- 比如,可以使用以下代码创建与 book 对象类似的新对象:- let bookCopy =JSON.parse(jsonText);//将JSON解析为JavaScript的对象- 注意, bookbookCopy 是两个完全不同的对象,没有任何关系。但是它们拥有相同的属性和值。- JSON.parse() 传入的JSON字符串必须是有效的,如果传入的 JSON 字符串无效,则会导致抛出错误。

序列化选项

  • JavaScriptJSON.stringify() 方法除了要序列化的对象,还可以接收两个参数。
  • 这两个参数可以用于指定其他序列化 JavaScript 对象的方式。 - 第一个参数是过滤器,可以是数组或函数;第二个参数是用于缩进结果 JSON 字符串的选项。- 单独或组合使用这些参数可以更好地控制 JSON 序列化。
  1. 过滤结果
  • 如果第二个参数是一个数组,那么 JSON.stringify() 返回的结果只会包含该数组中列出的对象属性。- 比如下面的例子:- <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>JavaScript序列化</title></head><body><script>let book ={ title:"富婆通讯录", authors:["CS@zeny","各大富婆"], edition:1, year:2021};let jsonText1 =JSON.stringify(book,["title","edition"]);//将属性"title"和"edition"序列化let jsonText2 =JSON.stringify(book,["title","edition","authors"]);//将属性"title","edition"和"authors"序列化 document.write("jsonText1 : "+ jsonText1);//输出jsonText1的内容 document.write("<br>");//换行 document.write("jsonText2 : "+ jsonText2);//输出jsonText2的内容</script></body></html>- 得到的结果为- jsonText1 : {"title":"富婆通讯录","edition":1}jsonText2 : {"title":"富婆通讯录","edition":1,"authors":["CS@zeny","各大富婆"]}
  • 如果第二个参数是一个函数,则行为又有不同。- 提供的函数接收两个参数:属性名( key )和属性值( value )。可以根据这个 key 决定要对相应属性执行什么操作。这个 key 始终是字符串,只是在值不属于某个键/值对时会是空字符串。- 为了改变对象的序列化,返回的值就是相应 key 应该包含的结果。注意,返回 undefined 会导致属性被忽略。- 下面看一个例子:- <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>JavaScript序列化</title></head><body><script>let book ={ title:"富婆通讯录", authors:["CS@zeny","各大富婆"], edition:1, year:2021, price:"100yuan"};let jsonText =JSON.stringify(book,(key, value)=>{switch(key){case"authors"://如果键是"authors"return value.join(",")//则将数组转换成字符串case"year"://如果键是"year"return5000;//则将value值置为5000case"edition"://如果键是"edition"returnundefined;//则将返回 undefined, 返回未定义则会忽略该属性,即忽略"edition"属性default:return value;//最后一定要提供默认返回值,以便返回其他属性传入的值}//函数基于键进行过滤});//第一次调用这个函数实际上会传入空字符串 key,值是 book 对象,这也解释了为啥最后默认返回值一定得是vaule,如果是其他则传不进book对象. document.write(jsonText);//输出jsonText的内容</script></body></html>- 输出结果 :- {"title":"富婆通讯录","authors":"CS@zeny,各大富婆","year":5000,"price":"100yuan"}
  • 注意,函数过滤器会应用到要序列化的对象所包含的所有对象,因此如果数组中包含多个具有这些属性的对象,则序列化之后每个对象都只会剩下上面这些属性。
  1. 字符串缩进
  • JSON.stringify()方法的第三个参数控制缩进和空格。在这个参数是数值时,表示每一级缩进的空格数。
  • 说明 : 如果第二个参数不需要填的话,就必须要用关键字null来代替- 比如 : let jsonText1 = JSON.stringify(book, null, 2);- 举个大栗子 :- <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>JavaScript序列化</title></head><body><script>let book ={ title:"富婆通讯录", authors:["CS@zeny","各大富婆"], edition:1, year:2021, price:"100yuan"};let jsonText1 =JSON.stringify(book,null,2);//每级缩进2个空格let jsonText2 =JSON.stringify(book,null,4);//每级缩进4个空格 console.log(jsonText1);//在控制台输出 console.log(jsonText2);//在控制台输出//说明: 如果使用document.write(); 函数在网页上输出会看不到空格,因为在网页上HTML语法直接忽略空格, 所以要用console.log()函数在控制台输出</script></body></html>- 输出效果 :- 请添加图片描述
  • 注意,除了缩进, JSON.stringify() 方法还为方便阅读插入了换行符。这个行为对于所有有效的缩进参数都会发生。(只缩进不换行也没什么用。)最大缩进值为 10,大于 10 的值会自动设置为 10。
  • 如果缩进参数是一个字符串而非数值,那么JSON字符串中就会使用这个字符串而不是空格来缩进。使用字符串,也可以将缩进字符设置为 Tab或任意字符。- 如两个连字符--, 一个Tab- <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>JavaScript序列化</title></head><body><script>let book ={ title:"富婆通讯录", authors:["CS@zeny","各大富婆"], edition:1, year:2021, price:"100yuan"};let jsonText1 =JSON.stringify(book,null,"--");//每级缩进字符串--let jsonText2 =JSON.stringify(book,null," ");//每级用Tab缩进, 注意引号内不是空格输入而是按一次Tab键输入let jsonText3 =JSON.stringify(book,null,4);//每级缩进4个空格 console.log(jsonText1);//在控制台输出 console.log(jsonText2);//在控制台输出 console.log(jsonText3);//在控制台输出//说明: 如果使用document.write(); 函数在网页上输出会看不到空格,因为在网页上HTML语法直接忽略了, 所以要用console.log()函数在控制台输出</script></body></html>- 效果 :- 请添加图片描述注意 : 使用字符串时同样有 10 个字符的长度限制。如果字符串长度超过 10,则会在第 10 个字符处截断。
  1. toJSON()方法
  • 当对象需要在 JSON.stringify() 之上自定义 JSON 序列化。此时,可以在要序列化的对象中添加 toJSON()方法,序列化时会基于这个方法返回适当的 JSON 表示。
  • 事实上,原生 > > Date> > 对象就有一个 > > toJSON()> > 方法,能够自动将 > > JavaScript> > 的 > > Date> > 对象转换为 ISO 8601 日期字符串(本质上与在Date 对象上调用 > > toJSON()> > 方法一样)。

  • 举个栗子 :
  • <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>JavaScript序列化</title></head><body><script>let book ={ title:"富婆通讯录", authors:["CS@zeny","各大富婆"], edition:1, year:2021, price:"100yuan",toJSON:function(){returnthis.title;}//这里 book 对象中定义的 toJSON() 方法简单地返回了图书的书名( this.title )。};let jsonText =JSON.stringify(book); console.log(jsonText);//在控制台输出</script></body></html>
  • 输出结果 : "富婆通讯录"
  • toJSON()方法可以返回任意序列化值,都可以起到相应的作用。如果对象被嵌入在另一个对象中,返回 undefined 会导致值变成 null ;或者如果是顶级对象,则本身就是 undefined

注意,箭头函数不能用来定义

toJSON()

方法。主要原因是箭头函数的词法作用域是全局作用域,在这种情况下不合适。

  • toJSON() 方法可以与过滤函数一起使用,因此理解不同序列化流程的顺序非常重要。在把对象传给 JSON.stringify() 时会执行如下步骤。
    1. 如果可以获取实际的值,则调用 toJSON() 方法获取实际的值,否则使用默认的序列化。2. 如果提供了第二个参数,则应用过滤。传入过滤函数的值就是第 1 步返回的值。3. 第 2 步返回的每个值都会相应地进行序列化。4. 如果提供了第三个参数,则相应地进行缩进。理解这个顺序有助于决定是创建 toJSON() 方法,还是使用过滤函数,或是两者都用。

解析选项

  • JSON.parse() 方法也可以接收一个额外的参数,这个函数会针对每个键/值对都调用一次。
  • 为区别于传给 JSON.stringify() 的起过滤作用的替代函数(replacer),这个函数被称为还原函数(reviver)。 - 实际上它们的格式完全一样,即还原函数也接收两个参数,属性名( key )和属性值( value ),另外也需要返回值
  • 如果还原函数返回 undefined ,则结果中就会删除相应的键。如果返回了其他任何值,则该值就会成为相应键的值插入到结果中。还原函数经常被用于把日期字符串转换为 Date 对象。

举个栗子 :

<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>JSON解析</title></head><body><script>let book ={
            title:"富婆通讯录",
            authors:["CS@zeny","各大富婆"],
            edition:1,
            year:2021,
            price:"100yuan",
            releaseDate:newDate(2021,01,01)//增加了releaseDate属性,是一个Date对象。};let jsonText =JSON.stringify(book);//这个对象在被序列化为JSON字符串后let bookCopy =JSON.parse(jsonText,//又被重新解析为一个对象 bookCopy(key, value)=> key =="releaseDate"?newDate(value): value);//这里的还原函数会查找 "releaseDate" 键,如果找到就会根据它的日期字符串创建新的 Date 对象alert("返回的年份:"+ bookCopy.releaseDate.getFullYear());//得到的 bookCopy.releaseDate 属性又变回了Date 对象,因此可以调用其 getFullYear()方法来获取年份。</script></body></html>

效果 :

请添加图片描述

附注 :

getFullYear()

是Date类下的方法;作用 : 返回 4 位数年(即 2021而不是 21)

JSON 的优点

JSON

是一种轻量级数据格式,可以方便地表示复杂数据结构。这个格式使用

JavaScript

语法的一个子集表示对象、数组、字符串、数值、布尔值和 null 。虽然

XML

也能胜任同样的角色,但

JSON

更简洁,

JavaScript

支持也更好。更重要的是,所有浏览器都已经原生支持全局 JSON 对象。

ENDING

参考书籍 : Javascript高级程序设计:第4版/ (美)马特·弗里斯比(Matt Frisbie)著;李松峰译. 北京:人民邮电出版社,2020.9 第23章 JSON P704.

标签: json javascript 前端

本文转载自: https://blog.csdn.net/honorzoey/article/details/122162686
版权归原作者 CS@zeny 所有, 如有侵权,请联系我们删除。

“轻量级数据格式 &mdash;&mdash; JSON”的评论:

还没有评论