JSON(Java Script Object Notation)是业界最为普遍的内部数据交换的轻量级协议,人机都方便读写。JSON语法非常精练,我们从它的BNF范式角度来学习可谓是最快速和最容易的学习方法。
JSON包含两种格式,分别用BNF表示就是:
-
1.name/value对的object格式
name/value.png
如下数据是符合上图格式要求的:
[root@VM_0_10_centos ~]# cat person.js
{ "name":"Mike", "age":34}
对照BNF图很好理解,name/value对一定出现在一对大括号里面,每对之间用逗号隔开。
每个name/value对中,name一定是json中的string类型数据,也即是我们常用的字符串,value是我们后面要定义的value类型。name和value之间用冒号隔开。
很显然,下面例子不符合格式要求:
[root@VM_0_10_centos ~]# cat person_err.js
{ "name":"Mike", "age"}
{ "name":"Mike", }
{ :"Mike", "age":34}
第一个例子:"age"后面的value没有定义。(错误)
第二个例子:定义了逗号,没有定义后续的name/value对。(错误)
第三个例子:第一个name/value对的name丢失了。(错误)
依照BNF图很容易看出和理解如何保证数据符合JSON的格式要求。
我们要知道,这里的string和value都还有特殊的格式要求,后面会介绍和学习。
-
2.value的array格式
value order.png
如下数据就是符合value的顺序列表格式的格式要求的:
[root@VM_0_10_centos ~]# cat persons.js
[ "Bill" , "Mike" , "John" ]
按照要求,value的array一定包含在一对方括号之间,这有限对的value的列表之间用逗号隔开。
按照图示,我们很容易理解如下的数据格式是不符合语法要求的:
[root@VM_0_10_centos ~]# cat persons_err.js
[ "Bill" , "Mike" , ]
[ , "Mike" , "John" ]
-
3.值value的构成定义
value.png
按照图示,我们能迅速明白了如何构成JSON中的所谓的值,第一类值就是字符串,第二类是数字,第三类是object,第四类是array,第五类和第六类是逻辑运算的true和false,最后一类就是null。而且在值的前后分别有whitespace。是不是很容易!
特殊的需要交代下:
- 这里有个递归的引用,object 可以作为value来使用。例如:
[root@VM_0_10_centos ~]# cat persons1.js
[ "Manager" , "HR department" , "level20",{ "name":"Mike", "age":34} ]
我们可以简单理解为方括号里面嵌套大括号。
这里的object 作为了value出行在array中。
- value构成的array也可以作为value再次递归出现。例如:
[[ "Manager" , "HR department" , "level20",{ "name":"Mike", "age":34} ],
[ "Senior Manager" , "IT department" , "level30",{ "name":"Bill", "age":50} ]]
我们简单理解为方括号里嵌套方括号。
怎样的值是字符串?怎样的值是数字?我们都通过图示来学习和掌握。
-
4.whitespace 的构成定义
image.png
我们看图识空白,是不是很容易的感觉,所以我们明白了JSON中的whitespace可以是真的什么都没有,也可以是若干的空格符、回车符、换行符、制表符构成。
[root@VM_0_10_centos ~]# cat persons1.js
[ "Bill"
, "Mike" , "John"
]
所以上面这个例子就是一个语法完全正确的JSON值的表示。虽然看起来七零八落的。
-
5.string的定义
JSON中最复杂的数据类型就是string了。看看下图,是不是比前面的BNF图都复杂?
string.png
string要么是一对空的双引号,要么就是除去一下几个特殊符号的任意字符串,unicode一并支持。
我们要首先认识这几个特殊字符符号:
第一个就是双引号:双引号本身构成了string格式定义的一部分,要表达string中的双引号,要用反斜线转义表达。
第二个就是反斜线:反斜线的有特殊的转义的作用。
其他几个特殊的控制符号必须以反斜线开头转义使用。
string中的双引号:\"
string中的斜线:\/
string中的反斜线:\\
string中的回车:\r
string中的换行:\n
string中的换页:\f
string中的制表符:\t
string中的unicode字符:\u
前面的都很好理解了,最后一个我们举例说明下:
[root@VM_0_10_centos ~]# cat string.js
{ "name":"\u8d3a", "age":34}
这个\u8d3a实际表示的是一个汉字"贺"。
学习完string,其他就是小菜了。
-
6 number的定义
number.png
这个图看起来像个迷宫,实际只要我们明白了数字的组成部分,就很容易了。
任何一个数,可以分成整数部分和小数部分,如果数很大,可以加上指数表达式。
整数部分的数字构成也很好理解,看看下图。
integer.png
是不是我们常见的数字的整数部分就是符合这样的规律的。
[root@VM_0_10_centos ~]# cat numbers.js
12345
-345
9876
111111
0.2222
23.e3
111.e-10
98.e+4
-345:负数,一定有个负号在最左端。
0.2222:纯小数,最左边整数部分是0。
9876:最左端是1-9中的任意一个数,后面是0-9任意数的任意组合。
紧接着是小数部分的定义。如图。
frac.png
0.2222:小数点后面,0-9任意数的任意组合,构成小数部分。
最后一个部分的定义是指数的定义。如图。
exp.png
23.e3:e(E)是指数部分的开始,e后面是符号位,然后后面是0-9的任意组合。
111.e-10:负指数必须要有负号。负号后面是0-9的任意组合。
98.e+4:正指数中,正号是可选的。
好了,整个JSON就学习完了,真正复杂的地方就是value定义的递归使用。我们使用一个稍微复杂的JSON数据来复习一下本篇的学习内容。
[root@VM_0_10_centos ~]# cat test_schema.js
{
"type": "object",
"properties": {
"first_name": { "type": "string" },
"last_name": { "type": "string" },
"age": { "type": "integer" },
"club": {
"type": "object",
"properties": {
"name": { "type": "string" },
"founded": { "type": "integer" }
},
"required": ["name"]
}
},
"required": ["first_name", "last_name", "age", "club"]
}
整个是一个object,该object由3对name/value对构成。
第一对name/value是"type": "object",很好理解了。
第二对name/value的value不是简单的string或者number,它是另一个object。这个object由5对name/value对构成。这个object的前面4对name/value的value又都是另外的object,最后一对的value是个array。
第三对name/value的value是由4个value构成的array。
总体分析还是比较简单的。通过上面的学习,我们对JSON的语法格式就有了一个比较深入的了解和学习,对常见的JSON数据格式,可以做到心中有数了。
网友评论