161 lines
8.3 KiB
Markdown
161 lines
8.3 KiB
Markdown
# 数据格式
|
||
|
||
看到这里,你一定对JSON中的对象具有一定的了解了,但是,我们依旧尚未关注对象中字段的值都允许什么样的类型。我们将目光看向上面的“缩进示例”所描述的文件。如果记忆力不错的话,你一定还记得我们说过这是附加包的清单文件。我们就再次来以这个清单文件为例,学习JSON中的值所允许的数据类型,或者说,数据格式。
|
||
|
||
## 数字
|
||
|
||
```json
|
||
{
|
||
"format_version": 2,
|
||
"header": {
|
||
},
|
||
"modules": [
|
||
]
|
||
}
|
||
```
|
||
|
||
JSON中的值允许使用**数字**(**Number**),例如上述的`"format_version": 2`中的值`2`。当然,数字未必是整数,JSON中允许**整数**(**Integer**,**int**)和**浮点数**(**Floating Number**,**float**)两种数字形式。浮点数即我们平常所说的“小数”,或者说“实数”,不过虽然可能会被称为“实数”或“实型”,但是事实上显然是只能接受“有理数”的输入,或者更准确地说,有限小数的输入。以下示例都属于数字数据格式:
|
||
|
||
```json
|
||
{
|
||
"height": 170,
|
||
"weight": 60.5,
|
||
"chest": 90.95,
|
||
"waist": 62.05,
|
||
"hip": 96.05
|
||
}
|
||
```
|
||
|
||
## 对象
|
||
|
||
```json
|
||
{
|
||
"format_version": 2,
|
||
"header": {
|
||
"description": "resourcePack.vanilla.description",
|
||
"name": "resourcePack.vanilla.name",
|
||
"uuid": "0575c61f-a5da-4b7f-9961-ffda2908861e",
|
||
"version": [0, 0, 1],
|
||
"min_engine_version": [1, 13, 0]
|
||
},
|
||
"modules": [
|
||
]
|
||
}
|
||
```
|
||
|
||
JSON中字段的值也可以是一个完整的对象,就比如这里`"header"`字段的值即是一个对象,这个对象中又含有`description"`等五个新的字段。对象常用来表达属性之间的包含关系。最外面的对象,在上述示例中也就是第一行和最后一行的花括号所括住的对象,被我们称为该JSON的**根对象**(**Root Object**)。
|
||
|
||
## 字符串
|
||
|
||
```json
|
||
{
|
||
"format_version": 2,
|
||
"header": {
|
||
"description": "resourcePack.vanilla.description",
|
||
"name": "resourcePack.vanilla.name",
|
||
"uuid": "0575c61f-a5da-4b7f-9961-ffda2908861e",
|
||
"version": [0, 0, 1],
|
||
"min_engine_version": [1, 13, 0]
|
||
},
|
||
"modules": [
|
||
]
|
||
}
|
||
```
|
||
|
||
除了数字和对象之外,JSON中也有一种用于表示“一段文本”的数据格式,那便是**字符串**(**String**)。顾名思义,字符串就是一列字符“串”在一起,即“一段文本”,为了能够使计算机正确解析字符串,正确“认识到”这是一个字符串,我们需要使用**英文直引号**`"`将字符串的两侧括住。以下便是一些字符串的示例:
|
||
|
||
```json
|
||
{
|
||
"name": "小明",
|
||
"gender": "",
|
||
"height": "170cm",
|
||
"weight": "60.5kg",
|
||
"chest": "90.95cm",
|
||
"waist": "62.05cm",
|
||
"hip": "96.05cm"
|
||
}
|
||
```
|
||
|
||
由于小明是我虚构的人物,而我并不想擅自假定小明的性别,所以我在`"gender"`字段里留了空,相邻的两个引号`""`也是一种字符串,这种字符串被称为**空字符串**(**Empty String**)。我们可以看到,除了字段的值可以是字符串之外, 字段的键也都是使用英文直引号`"`括起来的形式。虽然并不建议这么理解,但是如果你想的话,你也可以理解为“无论字段的值如何,**字段的键都必须要是字符串的形式**,只不过,字段的键不可以是空字符串”。
|
||
|
||
## 数组
|
||
|
||
```json
|
||
{
|
||
"format_version": 2,
|
||
"header": {
|
||
"description": "resourcePack.vanilla.description",
|
||
"name": "resourcePack.vanilla.name",
|
||
"uuid": "0575c61f-a5da-4b7f-9961-ffda2908861e",
|
||
"version": [0, 0, 1],
|
||
"min_engine_version": [1, 13, 0]
|
||
},
|
||
"modules": [
|
||
]
|
||
}
|
||
```
|
||
|
||
除了上述我们已经多次观察的值的类型之外,JSON还允许一种特殊的数据类型,这种数据类型被称为**数组**(**Array**)。我们可以观察到,与对象非常类似的是,数组也使用一种形式的括号来作为两边的边界,只不过,数组使用的是方括号`[]`而非花括号。
|
||
|
||
我们之前已经知道,对象中的每一个字段都有其“名字”,即它的键,但是,数组中的值并没有与之对应的键,它们唯一的不同在于它们在数组中出现的顺序,即谁是第0位,谁是第1位,谁是第2位等。数组中只有值,数组中每一个值被称为一个**元素**(**Element**)。
|
||
|
||
和对象可以拥有任意多的字段一样,数组理论上也可以拥有任意多的元素,但是,有些位置的数组受到游戏接口的限制,只有一部分元素是有效的,且可以被游戏读取。比如,上述示例中的`"version"`和`"min_engine_version"`都只有前三个元素可以被游戏读取并正确解析为版本号,而`"modules"`字段则可以接受并正确读取任意多的元素。不过,这也仅仅是受限于游戏引擎提供的接口而已,这并不是本节想要讲述的内容。单纯从JSON格式上来看,不论你在数组中放置多少个元素,这个JSON文件都是符合格式标准的。
|
||
|
||
```json
|
||
{
|
||
"format_version": 2,
|
||
"header": {
|
||
"description": "resourcePack.vanilla.description",
|
||
"name": "resourcePack.vanilla.name",
|
||
"uuid": "0575c61f-a5da-4b7f-9961-ffda2908861e",
|
||
"version": [0, 0, 1],
|
||
"min_engine_version": [1, 13, 0]
|
||
},
|
||
"modules": [
|
||
{
|
||
"description": "resourcePack.vanilla.description",
|
||
"type": "resources",
|
||
"uuid": "53644fac-a276-42e5-843f-a3c6f169a9ab",
|
||
"version": [0, 0, 1]
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
数组中和对象中字段的值所接受的类型并没有什么差别,比如上述例子中的`"modules"`数组的元素就是一个对象。数组中元素的顺序,或者说“位置”,被称为该元素的**索引**(**Index**)。注意,**索引都是从0开始计数的**,例如上述的`"modules"`数组只有一个元素,这个元素是一个对象,它的索引是0。
|
||
|
||
如果你还记得的话,我们一开始说过,JSON是从JavaScript语言中析取出来的一种格式。在JavaScript中,数组也是一种特殊的对象,或许是因为这个原因,在JSON中,人们有时也会使用一个JSON数组来作为JSON的根“对象”,这并非是一种错误的写法,只不过并不那么常见。以下是一个最外层(即根“对象”)是一个数组的示例:
|
||
|
||
```json
|
||
[
|
||
"en_US",
|
||
"zh_CN",
|
||
"zh_TW"
|
||
]
|
||
```
|
||
|
||
## 布尔值
|
||
|
||
为了纪念伟大的数学家与逻辑学家**乔治·布尔**(George Boole),人们将一种用于表示纯粹的“真”或“假”的概念的数据类型称为**布尔值**(**Boolean Value**,**boolean**,**bool**),这种值的类型被实现到了很多的计算机语言中,JSON中也不例外。在JSON中,我们使用`true`表示“**真**”或者“是”的概念,`false`表示“**假**”或者“否”的概念,二者皆为小写,不可以使用大写的形式。像`true`、`false`这样的预先给定了“只能这么写”的值在JSON中也被称为**字面量**(**Literal**),由于是直接的字面量,所以它们**不需要像字符串那样使用引号将自身括住**。以下是一个使用了布尔值的JSON示例:
|
||
|
||
```json
|
||
{
|
||
"name": "小明",
|
||
"is_chinese": true,
|
||
"is_american": false,
|
||
"is_british": false,
|
||
"is_japanese": false
|
||
}
|
||
```
|
||
|
||
## 空值
|
||
|
||
和布尔值一样,JSON中还有第三个字面量`null`,被称为**空值**(**Null**),用于代表“空”或“未知”的概念。空值`null`和数字中的`0`、字符串中的空字符串`""`、空对象`{}`、空数组`[]`都不同,它仅仅代表“这里什么都没有”或者“什么都不知道”。比如,我们可以问小明手里有几个苹果,如果回答“0”,那么我们就可以知道小明手里有0个苹果(即没有苹果),但是如果回答“Null”,结果就变成了我们无法知道小明手里有多少苹果,甚至小明有可能身患残疾,根本无法“手持”苹果了,这一点我们也无法从“Null”这个结果中肯定或否定。在一般的JSON编写中,我们并不经常会用到空值`null`,这个值一般是用于防止程序出现意外错误而引入的。注意,如同两个布尔值一样,`null`中的每一个字母也需要小写:
|
||
|
||
```json
|
||
{
|
||
"name": "小明",
|
||
"handed_apple_count": null
|
||
}
|
||
```
|