# 数据格式

看到这里,你一定对JSON中的对象具有一定的了解了,但是,我们依旧尚未关注对象中字段的值都允许什么样的类型。我们将目光看向上面的“缩进示例”所描述的文件。如果记忆力不错的话,你一定还记得我们说过这是附加包的清单文件。我们就再次来以这个清单文件为例,学习JSON中的值所允许的数据类型,或者说,数据格式。

# 数字

{
    "format_version": 2,
    "header": {
    },
    "modules": [
    ]
}

JSON中的值允许使用数字Number),例如上述的"format_version": 2中的值2。当然,数字未必是整数,JSON中允许整数Integerint)和浮点数Floating Numberfloat)两种数字形式。浮点数即我们平常所说的“小数”,或者说“实数”,不过虽然可能会被称为“实数”或“实型”,但是事实上显然是只能接受“有理数”的输入,或者更准确地说,有限小数的输入。以下示例都属于数字数据格式:

{
    "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 Valuebooleanbool),这种值的类型被实现到了很多的计算机语言中,JSON中也不例外。在JSON中,我们使用true表示“”或者“是”的概念,false表示“”或者“否”的概念,二者皆为小写,不可以使用大写的形式。像truefalse这样的预先给定了“只能这么写”的值在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
}

数字

对象

字符串

数组

布尔值

空值