# 对象

正如JSON的名字——“JavaScript对象表示法”所说的那样,JSON是用来表示一个JavaScript对象的文件格式。只不过,严谨地说,JSON的格式比JavaScript的对象格式还要严格一些,所以我们更愿意直接称呼JSON中表示的这种JavaScript对象为“JSON对象”,或直接与JavaScript中一样简称为对象Object)。

一个对象的特征,或者说标志,便是一对花括号{}。从左花括号{开始,中间写入一些内容,到右花括号}结束,这一整个内容便是一个对象。正如我们上面示例中看到的那样,一个JSON文件的全部内容便是一整个对象。注意,花括号必须成对出现,如果只有单独的一边的花括号,我们便无法确定从哪儿到哪儿才是一个对象,这种格式便是错误的JSON格式,自然也无法被程序正确解析。

以下便是一个最简单的对象:

{}

我们可以看到,这里的最右花括号之间什么内容都没有,这种对象自然被我们称为空对象Empty Object)。那么,如果要向对象中填充内容,我们应该采取什么样的格式呢?没错,答案就是我们在之前的示例中观察到的结果——使用字段来描述。

# 字段

字段是用作在对象中描述一对信息的格式,这对信息中有一部分是用来说明该字段是“用于说明什么属性的”,而另一部分是用来说明该字段“在上述说明的属性下给出的值是多少”。以一个人为例,其名字为小明,身高为170cm,体重为60kg。那么如果我们想把小明描述成对象中的字段,便可以按照如下格式来书写:

{
    "name": "小明",
    "height": 170,
    "weight": 60
}

每个字段的中间都存在一个英文冒号:,冒号的左侧我们称之为,右侧我们称之为。每两个两个字段之间使用英文逗号,分隔,用来代表他们是不同的字段。在上述示例中,"name""height""weight"都是键,而对应的"小明"17060则是它们各自的值。"name"字段结尾处的逗号用于分隔"name"字段和"height"字段,"height"字段结尾处的逗号用于分隔"height"字段和"weight"字段。"weight"字段之后没有其他字段了,所以无需再添加任何逗号,正如"name"字段之前也没有任何逗号一样。

逗号并非一定要写在字段的末尾,他们可以在两个字段之间的任何位置,比如下一个字段的开头。事实上,字段与字段之间,甚至键、值、冒号、逗号、花括号等元素之间,都可以存在任意数量的“空白Whitespace)字符”,空白字符包括空格符、制表符、换行符、回车符等。也就是说,不仅仅是逗号可以在空白字符中任意移动自己的位置,事实上,上述小明的示例用下面所展示的任意一种写法都是可行且等价的:

  • 完全收紧:

    {"name":"小明","height":170,"weight":60}
    
  • 适当空格:

    { "name": "小明", "height": 170, "weight": 60 }
    
  • 随意空格:

    {    "name"  :  "小明",    "height" : 170,  "weight":       60   }
    
  • 标准换行:

    {
        "name": "小明",
        "height": 170,
        "weight": 60
    }
    
  • 逗号左移:

    {
        "name": "小明"
       ,"height": 170
       ,"weight": 60
    }
    
  • 放飞自我:

    {
              "name":   "小明" ,
      "height"  :    170
           ,
           "weight" :
       60
                              }
    

当然,虽然对于计算机来说,上述的写法都会解析为同样的内容,但是对于人类来说,有些写法还是“为时过早”了。从我们自身和其他人在查阅我们的代码时的可读性的角度出发,上述示例中的“适当空格”和“标准换行”标签页展示的格式分别是在“同一行写”和“换行写”时最为推荐的格式。当然,“完全收紧”的格式也不是毫无用处的,人们在网络传输时往往采用完全收紧的方式剔除掉所有的“无关字符”,以保证文件是“最小化”的,从而使消耗的流量降到最低。

同时,我们注意到了上述的换行书写示例中,我们的三个字段并没有和两个花括号处在同一竖直线上,换句话说,我们在三个字段的开头分别添加了若干空格。这种行为被称为缩进Indentation)。适当的缩进可以使我们的代码更加规范和可读,同时也方便我们检查文件格式有没有出现错误。比如,在上述示例中,我们将一个对象的内容缩进之后,内容中的各字段在同一个竖直线上对齐,对象两侧的花括号在另一个竖直线上互相对齐,这不仅可以快速帮我们定位到该对象的字段,帮助我们快速观察到字段的数目和各自的值,同时也可以帮助我们检查该对象的两个花括号是否成对,有没有“落单”的括号出现等内容,因此,良好的缩进习惯是一个优秀的开发者养成具备习惯之一,否则,如果最后的代码真的写成了上述示例中“放飞自我”的格式,如并非故意,那可真要贻笑大方了。

一般而言,我们可以使用多种字符充当缩进用的空白字符,但是一旦选择某种字符,便推荐将其在全文统一。常用的缩进用空白字符有单个制表符(即1个TAB),2个、3个或4个空格,当然,你选择其他数量的空格或制表符也是可行的,毕竟这并不违背JSON文件的规范。

  • 1个制表符:

    {
    	"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]
    		}
    	]
    }
    
  • 2个空格:

    {
      "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]
        }
      ]
    }
    
  • 3个空格:

    {
       "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]
          }
       ]
    }
    
  • 4个空格:

    {
        "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]
            }
        ]
    }
    

字段