# 数据格式
看到这里,你一定对JSON中的对象具有一定的了解了,但是,我们依旧尚未关注对象中字段的值都允许什么样的类型。我们将目光看向上面的“缩进示例”所描述的文件。如果记忆力不错的话,你一定还记得我们说过这是附加包的清单文件。我们就再次来以这个清单文件为例,学习JSON中的值所允许的数据类型,或者说,数据格式。
# 数字
{
"format_version": 2,
"header": {
},
"modules": [
]
}
JSON中的值允许使用数字(Number),例如上述的"format_version": 2
中的值2
。当然,数字未必是整数,JSON中允许整数(Integer,int)和浮点数(Floating Number,float)两种数字形式。浮点数即我们平常所说的“小数”,或者说“实数”,不过虽然可能会被称为“实数”或“实型”,但是事实上显然是只能接受“有理数”的输入,或者更准确地说,有限小数的输入。以下示例都属于数字数据格式:
{
"height": 170,
"weight": 60.5,
"chest": 90.95,
"waist": 62.05,
"hip": 96.05
}
# 对象
{
"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)。
# 字符串
{
"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)。顾名思义,字符串就是一列字符“串”在一起,即“一段文本”,为了能够使计算机正确解析字符串,正确“认识到”这是一个字符串,我们需要使用英文直引号"
将字符串的两侧括住。以下便是一些字符串的示例:
{
"name": "小明",
"gender": "",
"height": "170cm",
"weight": "60.5kg",
"chest": "90.95cm",
"waist": "62.05cm",
"hip": "96.05cm"
}
由于小明是我虚构的人物,而我并不想擅自假定小明的性别,所以我在"gender"
字段里留了空,相邻的两个引号""
也是一种字符串,这种字符串被称为空字符串(Empty String)。我们可以看到,除了字段的值可以是字符串之外, 字段的键也都是使用英文直引号"
括起来的形式。虽然并不建议这么理解,但是如果你想的话,你也可以理解为“无论字段的值如何,字段的键都必须要是字符串的形式,只不过,字段的键不可以是空字符串”。
# 数组
{
"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文件都是符合格式标准的。
{
"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的根“对象”,这并非是一种错误的写法,只不过并不那么常见。以下是一个最外层(即根“对象”)是一个数组的示例:
[
"en_US",
"zh_CN",
"zh_TW"
]
# 布尔值
为了纪念伟大的数学家与逻辑学家乔治·布尔(George Boole),人们将一种用于表示纯粹的“真”或“假”的概念的数据类型称为布尔值(Boolean Value,boolean,bool),这种值的类型被实现到了很多的计算机语言中,JSON中也不例外。在JSON中,我们使用true
表示“真”或者“是”的概念,false
表示“假”或者“否”的概念,二者皆为小写,不可以使用大写的形式。像true
、false
这样的预先给定了“只能这么写”的值在JSON中也被称为字面量(Literal),由于是直接的字面量,所以它们不需要像字符串那样使用引号将自身括住。以下是一个使用了布尔值的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
中的每一个字母也需要小写:
{
"name": "小明",
"handed_apple_count": null
}