使用json、yaml、toml作為配置文件,你知道他們的區(qū)別嗎

前言

配置文件,不言而喻,主要是我們進(jìn)行項(xiàng)目和工程配置的文件。

如果是站在前端角度說(shuō)的話,我們最常接觸的就是 json以及 js類(lèi)型的文件,這種形式的配置寫(xiě)法對(duì)前端非常友好,因?yàn)槎际俏覀兪煜さ?JS 對(duì)象結(jié)構(gòu),如:

  • package.json
  • webpack.config.js
  • babel.config.js
  • vue.config.js

不過(guò),隨著技術(shù)的更新迭代,也涌現(xiàn)出一些新的配置文件格式,相比較而言,原有的文件格式好像也變得不是那么好用了。雖然在此之前,json+js用著也不錯(cuò),不過(guò),當(dāng)新的工具出現(xiàn)后,尤其是在你深度體驗(yàn)與使用之后,可能會(huì)發(fā)現(xiàn)事情似乎有點(diǎn)那么不一樣了,感覺(jué)新的玩意就是好啊??,也便開(kāi)始嫌棄之前的家伙了~

不過(guò),我們要站在不同角度思考問(wèn)題,從新工具誕生的角度看,其誕生必然有著一定的歷史背景存在,如:

  1. 舊工具在某些場(chǎng)景表現(xiàn)吃力,需要更優(yōu)的替代方案
  2. 舊的寫(xiě)法和模式在某些場(chǎng)景下有著明顯的短板和缺陷,需要更進(jìn)一步的完善方案

背景

最近在做開(kāi)源項(xiàng)目的時(shí)候,在開(kāi)發(fā)功能時(shí),考慮到不同場(chǎng)景、不同用戶的不同需求,在開(kāi)始設(shè)計(jì)功能時(shí)就考慮到預(yù)留一定的可定制窗口方便用戶進(jìn)行定制化配置。當(dāng)然,在功能不斷開(kāi)發(fā)進(jìn)行時(shí),以及后期的迭代拓展時(shí),都會(huì)源源不斷的誕生出各種小功能和定制需求,因此,對(duì)于擁有一個(gè)足夠簡(jiǎn)單、易用、拓展的配置文件是相當(dāng)有必要的。

它應(yīng)該具備以下基本能力:

  1. 支持注釋:對(duì)于配置文件來(lái)說(shuō),注釋的重要性不必多說(shuō),它需要描述每個(gè)配置字段的作用
  2. 足夠簡(jiǎn)單:語(yǔ)法足夠簡(jiǎn)單,用法足夠簡(jiǎn)單,上手足夠簡(jiǎn)單;至少保證新人能很快上手使用
  3. 方便讀寫(xiě):對(duì)于用戶來(lái)說(shuō),應(yīng)該是可讀性非常高的,符合人類(lèi)語(yǔ)言習(xí)慣的,概覽之后可以快速上手配置

在此之前的版本,我已經(jīng)針對(duì)該想法做了初步的實(shí)施落地,從個(gè)人經(jīng)驗(yàn)來(lái)說(shuō),我之前在搞 CI/CD 自動(dòng)化部署相關(guān)的東西時(shí),寫(xiě)過(guò)一些 github action(配置文件為yaml格式),因此,對(duì)于yaml語(yǔ)法算是有些了解。

從使用感受上來(lái)說(shuō),它語(yǔ)法更簡(jiǎn)潔、支持注釋,所以,我果斷選擇了yaml作為我對(duì)于項(xiàng)目的配置文件格式。

不過(guò),在這段時(shí)間的使用過(guò)程中,我也發(fā)現(xiàn)了yaml存在的一些問(wèn)題,因此,最近我又重新思考了一下下這個(gè)問(wèn)題:

  1. 是繼續(xù)按照傳統(tǒng)的js文件的對(duì)象寫(xiě)法呢?
  2. 還是繼續(xù)使用yaml作為配置文件使用呢?
  3. 還是進(jìn)一步研究一些其他類(lèi)型的配置文件呢?
  4. 這些配置文件類(lèi)型又有啥本質(zhì)區(qū)別呢?

抱著學(xué)習(xí)的心理,咱不能在遇到問(wèn)題的時(shí)候就選擇逃避呀,那么本篇文章也算是對(duì)不同類(lèi)型配置文件的一種研究和學(xué)習(xí)了。

簡(jiǎn)單介紹

JSON

JSON的定義一般是作為數(shù)據(jù)格式,它通常用于序列化、結(jié)構(gòu)化數(shù)據(jù)并通過(guò)網(wǎng)絡(luò)進(jìn)行交換,通常發(fā)生在服務(wù)器與 Web 應(yīng)用之間。不過(guò)也有很多工具將其作為配置文件使用。

JSON 其實(shí)完全可以當(dāng)成是 JS 對(duì)象的形式進(jìn)行理解、使用。

其實(shí)使用JSON作為配置文件也有其一定的優(yōu)勢(shì):

  1. 語(yǔ)法非常簡(jiǎn)單,純粹的鍵值對(duì)結(jié)構(gòu)
  2. 很多編程語(yǔ)言的標(biāo)準(zhǔn)庫(kù)都支持 JSON,比如:在JS當(dāng)中你可以直接引入讀取
  3. 現(xiàn)在幾乎所有的工具都提供 JSON 支持,包括語(yǔ)法突出顯示、自動(dòng)格式化、驗(yàn)證工具等。
  4. 采用人類(lèi)可讀的輕量級(jí)文本,只需更少的編碼,處理速度更快

但是,也因?yàn)槠洫?dú)特的定位,它天生就注定了并不適合作為配置文件使用,原因也很明顯:

  1. 不支持注釋:對(duì)于配置文件來(lái)說(shuō),注釋的重要性不言而喻,但是JSON不支持添加注釋?zhuān)?code>JSON 作為一種數(shù)據(jù)交換格式,也不需要注釋??)
  2. 語(yǔ)法過(guò)于嚴(yán)格:鍵和字符串必須使用""雙引號(hào)(其實(shí)對(duì)于鍵來(lái)說(shuō),并不需要使用引號(hào)),結(jié)尾不允許有逗號(hào)(除了結(jié)尾都必須有逗號(hào),哈哈~)
  3. 多余的最外層大括號(hào):作為配置文件來(lái)說(shuō),最外層的大括號(hào)也顯得有些多余(這也是其作為交換數(shù)據(jù)格式的特點(diǎn),為了界定不同的對(duì)象)

雖然大家都很熟悉了,我們還是按流程看下基本用法,方便接下來(lái)做對(duì)比,如下:

{
  "name": "cat",
  "desc": {
    "color": "orange",
    "age": 1
  }
}

可以看出JSON作為數(shù)據(jù)格式,還是比較合適且優(yōu)秀的,但是作為配置文件來(lái)說(shuō),總覺(jué)得是力氣使錯(cuò)了方向??

YAML

YAML 是一種數(shù)據(jù)序列化語(yǔ)言,通常用于編寫(xiě)配置文件(它的流行和 k8s 脫不了關(guān)系??~)。

語(yǔ)法規(guī)則:

  • 大小寫(xiě)敏感
  • 使用縮進(jìn)表示層級(jí)關(guān)系
  • 縮進(jìn)時(shí)不允許使用Tab鍵,只允許使用空格。
  • 縮進(jìn)的空格數(shù)目不重要,只要相同層級(jí)的元素左側(cè)對(duì)齊即可
  • # 表示注釋?zhuān)瑥倪@個(gè)字符一直到行尾,都會(huì)被解析器忽略。
  • 文件拓展名為 .yaml.yml

支持的數(shù)據(jù)格式:

  • 對(duì)象:鍵值對(duì)的集合,又稱(chēng)為映射/ 哈希 / 字典
  • 數(shù)組:一組按次序排列的值,又稱(chēng)為序列 / 列表
  • 純量:?jiǎn)蝹€(gè)的、不可再分的值,可以理解為基本類(lèi)型

以下數(shù)據(jù)類(lèi)型都屬于 JavaScript 的純量:

字符串、布爾值、整數(shù)、浮點(diǎn)數(shù)、Null、時(shí)間、日期

其特點(diǎn)如下:

  1. 有更好的可讀性,對(duì)用戶更友好
  2. 簡(jiǎn)潔和強(qiáng)大,寫(xiě)法簡(jiǎn)潔,也有復(fù)雜的語(yǔ)法支持不同功能
  3. 是JSON的超集,JSON 文件在 YAML 中有效
  4. 使用 Python 風(fēng)格的縮進(jìn)來(lái)表示嵌套

如果說(shuō)到缺點(diǎn)的話,那和它的特點(diǎn)也是密不可分的

  1. 因?yàn)椴皇窃С值母袷剑煌脚_(tái)需要專(zhuān)門(mén)的解析工具(如:在JS中使用需要使用js-yaml解析,在線轉(zhuǎn)換
  2. 簡(jiǎn)單使用,基本語(yǔ)法夠簡(jiǎn)單;但是進(jìn)階使用,語(yǔ)法就比較復(fù)雜了,對(duì)于多行字符串的處理也有待優(yōu)化,尤其是結(jié)合縮進(jìn)語(yǔ)法一起
  3. 縮進(jìn)語(yǔ)法,如果搞錯(cuò)了縮進(jìn)或者沒(méi)看清,夠你定位問(wèn)題的了

按慣例,看下基本用法:

# 我是注釋
name: cat
desc:
  color: orange
  age: 1
  date: 2022-09-01 16:10:01

同時(shí)上面的內(nèi)容也可以這樣寫(xiě):

name: cat
desc: { color: orange, age: 1, date: 2022-09-01 16:10:01 } # JSON的超集

轉(zhuǎn)為JS如下:

{ 
  name: 'cat', 
  desc: { 
    color: 'orange', 
    age: 1,
    date: 'Fri Sep 02 2022 00:10:01 GMT+0800 (中國(guó)標(biāo)準(zhǔn)時(shí)間)' // new Date
  } 
}

TOML

全稱(chēng) Tom's Obvious, Minimal Language,意為語(yǔ)義明顯的、配置最小化的的語(yǔ)言。

官方描述:

為人而生的配置文件格式(好屌的感覺(jué)??~)。

TOML 旨在成為一個(gè)語(yǔ)義明顯且易于閱讀的最小化配置文件格式。TOML 被設(shè)計(jì)成可以無(wú)歧義地映射為哈希表。TOML 應(yīng)該能很容易地被解析成各種語(yǔ)言中的數(shù)據(jù)結(jié)構(gòu)。

  1. TOML 以人為先
    • 語(yǔ)義明顯易于閱讀
    • 能無(wú)歧義地映射為哈希表
    • 易于解析成各種語(yǔ)言中的數(shù)據(jù)結(jié)構(gòu)
  2. TOML 具備實(shí)用的原生類(lèi)型
    • 鍵/值對(duì)
    • 數(shù)組
    • 內(nèi)聯(lián)表
    • 表數(shù)組
    • 整數(shù) & 浮點(diǎn)數(shù)
    • 布爾值
    • 日期 & 時(shí)刻,帶可選的時(shí)區(qū)偏移
  3. TOML 受到廣泛支持
    • TOML 已經(jīng)擁有大多數(shù)當(dāng)今使用的最流行的編程語(yǔ)言的實(shí)現(xiàn):C、C#、C++、Clojure、Dart、Elixir、Erlang、Go、Haskell、Java、Javascript、Lua、Objective-C、Perl、PHP、Python、Ruby、Swift、Scala……以及更多。

語(yǔ)法規(guī)則:

  • 大小寫(xiě)敏感
  • 文件必須是合法的 UTF-8 編碼的 Unicode 文檔
  • 簡(jiǎn)潔、清晰的 = 寫(xiě)法(name = "cat"
  • 字符串需要由引號(hào)(")包裹
  • 表寫(xiě)法,鍵值對(duì)的集合,由表頭定義,連同方括號(hào)作為單獨(dú)的行出現(xiàn)
  • # 表示注釋
  • 文件拓展名為 .toml

其特點(diǎn)如下:

  1. 寫(xiě)法符合直覺(jué)、簡(jiǎn)單清晰
  2. 鍵名寫(xiě)法強(qiáng)大,鍵名可以是裸露的,引號(hào)引起來(lái)的,或點(diǎn)分隔的。
  3. 對(duì)字符串支持完善,基本字符串、多行基本字符串、字面量和多行字面量
  4. 表寫(xiě)法功能強(qiáng)大,鍵值對(duì)、數(shù)組、嵌套寫(xiě)法等

缺點(diǎn):

  1. 不是原生支持的格式,不同平臺(tái)需要專(zhuān)門(mén)的解析工具(如:在JS中使用需要使用@ltd/j-toml解析,在線轉(zhuǎn)換
  2. 屬于比較新型的格式,社區(qū)認(rèn)知度不高
  3. 新人對(duì)核心語(yǔ)法“表”需要適應(yīng)

基本用法如下:

# 我是注釋
name = "cat"

[desc]
color = "orange" 
age = 1 
date = 2022-09-01 16:10:01

你也可以這樣寫(xiě):

name = "cat"

desc.color = "orange" 
desc.age = 1 
desc.date = 2022-09-01 16:10:01

轉(zhuǎn)為JS如下:

{ 
  name: 'cat', 
  desc: { 
    color: 'orange', 
    age: 1,
    date: '2022-09-01T16:10:01'
  } 
}

用法對(duì)比

其實(shí)站在配置文件的角度思考,我們最關(guān)心的就是鍵值對(duì)寫(xiě)法(一個(gè)屬性控制一個(gè)功能點(diǎn)),誰(shuí)能做到在使用時(shí)讀寫(xiě)更方便,誰(shuí)也就更具有優(yōu)勢(shì)。

基本上就是一個(gè)對(duì)象結(jié)構(gòu),數(shù)據(jù)類(lèi)型符合字符串、對(duì)象、數(shù)組、布爾值、日期、數(shù)值也就差不多了

{ 
  "key" : value // 這里的 value 應(yīng)可以是以上的任何類(lèi)型
}

字符串

1?? 簡(jiǎn)單字符串用法

  • json寫(xiě)法:

    { 
      "name" : "cat"
    }
    

    最外層花括號(hào) {} 不可缺少,且不主持添加注釋?zhuān)?code>key 和 value 都需要使用引號(hào) "" 進(jìn)行包裹

  • yaml寫(xiě)法:

    name: cat # 貓
    

    默認(rèn)不需要使用引號(hào) "" 進(jìn)行包裹(用引號(hào)包裹結(jié)果也是一樣的),簡(jiǎn)單字符串使用非常簡(jiǎn)單,對(duì)于多行字符串則有所不同。

    特別注意的是:冒號(hào) : 后面要有空格,這符合 yaml 后面的所有語(yǔ)法規(guī)范

  • toml寫(xiě)法:

    name = "cat"
    

    有沒(méi)有空格無(wú)所謂,不影響解析,value部分需要按照字符串的寫(xiě)法,使用引號(hào) "" 進(jìn)行包裹

2?? 多行字符串

有些場(chǎng)景我們可能會(huì)定義很長(zhǎng)的一段字符串,默認(rèn)展示肯定是在一行顯示的,這樣既不好讀也不好維護(hù),尤其針對(duì)一些 shell 命令,我們?cè)谇岸斯こ讨袘?yīng)該見(jiàn)過(guò)不少這樣的。

我舉個(gè)列子:

"scripts": {
  "dev": "webpack-dev-server --base test/ --port 8081 --config build/webpack.dev.config.js",
  "lint:fix:utils": "eslint --fix \"./packages/utils/**\" --ext .js,.ts,.json"
}
  • json寫(xiě)法:

    不支持

  • yaml寫(xiě)法:

    # 注意縮進(jìn),第二行、第三行開(kāi)頭有空格(必須這樣寫(xiě))
    dev: webpack-dev-server --content-base test/ 
      --port 8081 
      --config build/webpack.dev.config.js
    

    字符串可以寫(xiě)成多行,從第二行開(kāi)始,必須有一個(gè)單空格縮進(jìn)。換行符會(huì)被轉(zhuǎn)為空格。

  • toml寫(xiě)法:

    dev = """
    webpack-dev-server --base test/ 
    --port 8081 
    --config build/webpack.dev.config.js
    """
    

    多行基本字符串由三個(gè)引號(hào)包裹,允許折行。

    官方規(guī)范:緊隨開(kāi)頭引號(hào)的那個(gè)換行會(huì)被去除,其它空白和換行會(huì)被原樣保留。

    特別注意:@ltd/j-toml解析庫(kù)目前支持自定義拼接,比如你想要以 ' '空格進(jìn)行拼接,而不使用換行'\n'拼接(TOML.parse(data, { joiner: ' ' })),以本例舉例,我換行是為了易讀,在解析之后的命令應(yīng)該還是一行的、一個(gè)整體的,就可以使用這種方式

    你還可以用行末反斜杠自動(dòng)剔除非空白字符前的任何空白字符:

    dev = """
    webpack-dev-server --base test/ \
          --port 8081 \
          --config build/webpack.dev.config.js \
    """
    

    解析結(jié)果如下:

    {
      dev: 'webpack-dev-server --base test/ --port 8081 --config build/webpack.dev.config.js'
    }
    

3?? 字面量字符串

為了方便理解,你把它當(dāng)成JS的模板字符串即可,沒(méi)有轉(zhuǎn)義行為,所見(jiàn)即所得。

這里以保留換行為例說(shuō)明:

  • json寫(xiě)法:

    不支持,JSON只能用引號(hào)"",但是如果你想保留類(lèi)似換行操作符一樣的東西,你可以這樣做

    { 
      "hi": "echo hello \n world \n 我是小明",
      "ha": "echo \"hello\" \"world\""
    }
    

    很煩,看著就難受的一批,寫(xiě)法也很操蛋~,我只能說(shuō)“打擾了”??

    換行需要添加 \n,以及你要是想在JSON中輸出引號(hào)"",就必須進(jìn)行轉(zhuǎn)義

  • yaml寫(xiě)法:

    在首行加一個(gè) | 符號(hào)即可,還是蠻簡(jiǎn)單的,縮進(jìn)一定要把握好~

    hi: |
      echo hello
      world
      我是小明
    

    解析為JS如下:

    { hi: 'echo hello\nworld\n我是小明\n' }

    • 如果你想保留文字塊末尾的換行,可以使用 |+
    • 如果你想刪除字符串末尾的換行,可以使用 |-
    hi: |-
      echo hello
      world
      我是小明
    

    解析為JS如下:

    { hi: 'echo hello\nworld\n我是小明' }

  • toml寫(xiě)法:

    字面量字符串由單引號(hào)包裹,不能換行(不會(huì)進(jìn)行任何轉(zhuǎn)義)

    path = 'C:\Users\nodejs\templates'
    path2 = '\\User\admin$\system32'
    quoted = 'Tom "Dubs" Preston-Werner'
    regex = '<\i\c*\s*>'    
    

    多行字面量字符串兩側(cè)各有三個(gè)單引號(hào)來(lái)包裹,允許換行。

    # 三個(gè)單引號(hào)包裹
    hi = '''
    echo 
    hello 
    world 我是小明
    '''
    

    解析為JS如下:

    { hi: 'echo \nhello \nworld 我是小明\n' }

    解析規(guī)則TOML.parse(data, { joiner: '\n' })

字符串用法小結(jié)

總的來(lái)說(shuō),JSON對(duì)于字符串的支持還是比較弱的,對(duì)于多行字符串等寫(xiě)法使用比較吃力;yaml總體來(lái)說(shuō)簡(jiǎn)單方便,對(duì)字符串的支持還是不錯(cuò)的,相關(guān)解析庫(kù)也很易用,唯一需要注意的就是縮進(jìn)需要把控好;如果要說(shuō)對(duì)字符串的支持能力,toml是最強(qiáng)的毋庸置疑,也沒(méi)有縮進(jìn)語(yǔ)法的擔(dān)憂,幾乎支持你所能相到的任何場(chǎng)景,不過(guò),目前確實(shí)存在使用量不高,第三方解析庫(kù)不太穩(wěn)定的問(wèn)題。

npm周下載量(Weekly Downloads)大致如下:

  • js-yaml53,724,459
  • @ltd/j-toml33,951 (1.0版本后官方指定的解析庫(kù))
  • toml666,591(0.4版本,不活躍)

千萬(wàn)級(jí)別和萬(wàn)級(jí)別的對(duì)比~

@ltd/j-toml解析庫(kù)對(duì)于存在多行字符串的toml文件進(jìn)行解析時(shí),必須要手動(dòng)指定拼接規(guī)則({ joiner: '' }),有點(diǎn)奇怪,不過(guò),這樣也使得我們?cè)谔幚矶嘈凶址畷r(shí),可以自定義拼接規(guī)則,以此實(shí)現(xiàn)不同的效果(要是說(shuō)對(duì)于一個(gè)文件內(nèi)多個(gè)多行字符串選擇不同的處理方式,有待商榷)

對(duì)象

對(duì)象寫(xiě)法還是非常普遍的,對(duì)于該核心語(yǔ)法的掌握還是很有必要的,其實(shí)也是鍵值對(duì)的范疇,舉例如下:

1?? 簡(jiǎn)單用法

  • json寫(xiě)法:

    {
      "desc": {
        "color": "red",
        "eaten": false,
        "age": 1
      }
    }
    

    對(duì)于JSON來(lái)說(shuō),還是老樣子,不支持注釋?zhuān)?strong>鍵必須用引號(hào)包括,如果值為字符串也要使用引號(hào)進(jìn)行包裹,非字符串類(lèi)型可以不用引號(hào)包裹

  • yaml寫(xiě)法:

    # 描述
    desc:
      color: red # 顏色
      eaten: false
      age: 1
    

    解析為JS如下:

    { 
      desc: { 
        color: 'red', 
        eaten: false, 
        age: 1 
      } 
    }
    

    可以發(fā)現(xiàn),yaml是可以很好地識(shí)別非字符串類(lèi)型的,數(shù)值類(lèi)型和布爾值都正確轉(zhuǎn)義

  • toml寫(xiě)法:

    # 描述
    [desc]
    color: red # 顏色
    eaten: false
    age: 1
    

    對(duì)象在toml中稱(chēng)為(也被稱(chēng)為哈希表或字典),是鍵值對(duì)的集合,它們由表頭定義,連同方括號(hào)作為單獨(dú)的行出現(xiàn)([desc])。

    對(duì)于toml來(lái)說(shuō),鍵名可以是裸露的,引號(hào)引起來(lái)的,或點(diǎn)分隔的(十分強(qiáng)大的能力)。

    解析為JS如下:

    解析規(guī)則:TOML.parse(data, { bigint: Number.MAX_SAFE_INTEGER })

    只要在超過(guò) Number.MAX_SAFE_INTEGER 這個(gè)范圍后,才會(huì)啟用 BigInt,一般整型寫(xiě)法用這個(gè)就行了

    { 
      desc: { 
        color: 'red', 
        eaten: false, 
        age: 1 
      } 
    }
    

    可以發(fā)現(xiàn),yaml是可以很好地識(shí)別非字符串類(lèi)型的,數(shù)值類(lèi)型和布爾值都正確轉(zhuǎn)義

2?? 復(fù)雜一些的用法

在使用對(duì)象時(shí)也會(huì)遇到多個(gè)對(duì)象結(jié)構(gòu)與嵌套的情況,如下:

  • json寫(xiě)法:

    {
      "desc": {
        "color": "red",
        "eaten": false,
        "age": 1
      },
      "animals": {
        "dog": {
          "color": "black"
        },
        "cat": {
          "color": "red"
        }
      }
    }
    
  • yaml寫(xiě)法:

    desc:
      color: red
      eaten: false
      age: 1
    animals:
      dog:
        color: black
      cat:
        color: red
    

    yaml寫(xiě)法還是滿簡(jiǎn)單清晰地,控制好縮進(jìn)一切OK

  • toml寫(xiě)法:

    [desc]
    color = "red" # 顏色
    eaten = false
    age = 1
    
    [animals]
    dog.color = "black"
    cat.color = "red"
    

    官方推薦使用標(biāo)準(zhǔn)的表寫(xiě)法([desc]作為表頭),每個(gè)表可以理解為一個(gè)對(duì)象體。不過(guò),因?yàn)?toml強(qiáng)大的語(yǔ)法系統(tǒng),你甚至可以直接使用點(diǎn).寫(xiě)法,不過(guò)為了規(guī)范和易讀推薦使用官方寫(xiě)法。

    你可以這樣寫(xiě):

    desc.color = "red" # 顏色
    animals.dog.color = "black"
    

    你還可以這樣寫(xiě):

    desc.color = "red" # 顏色
    
    [animals.dog]
    color = "black"    
    

    你甚至可以這樣寫(xiě):

    # toml對(duì)于鍵的解析能力十分強(qiáng)大,其他特殊寫(xiě)法都會(huì)被標(biāo)準(zhǔn)化處理
    desc."color" = "red" # 顏色
    animals .    "dog" .color = "black"
    

    解析為JS如下:

    {
      desc: { color: 'red' },
      animals: { 
        dog: { 
          color: 'black' 
        } 
      },
    }
    

對(duì)象用法小結(jié)

總的來(lái)說(shuō),JSON對(duì)于對(duì)象的寫(xiě)法支持還是蠻OK的,但是需要指出的是,JSON不支持注釋?zhuān)@是硬傷,而且和另外兩個(gè)格式相比較而言,寫(xiě)法也是略顯繁瑣;yaml總體來(lái)說(shuō)挺不錯(cuò)的,寫(xiě)法簡(jiǎn)潔、清爽,我還是蠻喜歡的,需要指出的是對(duì)于縮進(jìn)的處理一定要注意,yaml語(yǔ)法規(guī)范嚴(yán)格,一個(gè)縮進(jìn)不對(duì)就會(huì)解析錯(cuò)誤;就目前而言,toml在對(duì)象語(yǔ)法和使用上優(yōu)勢(shì)明顯,寫(xiě)法也是十分簡(jiǎn)單,而且其對(duì)鍵名的寫(xiě)法支持異常強(qiáng)大,極大的豐富了不同場(chǎng)景下的需求,不過(guò),需要指出的是,從易讀和已維護(hù)性考慮,還是推薦按照官方規(guī)范的寫(xiě)法使用。

數(shù)組與嵌套組合

數(shù)組以及JSON數(shù)組等常見(jiàn)用法的對(duì)比舉例,如下:

1?? 數(shù)組的基本用法

  • json寫(xiě)法:

    {
      "desc": [ "red", false, { "color": "red", "age": 1 } ] 
    }
    
  • yaml寫(xiě)法:

    desc:
      - red
      - false
      - color: red # 數(shù)組內(nèi)的對(duì)象寫(xiě)法需要注意
        age: 1 # 同一對(duì)象下的項(xiàng)(開(kāi)頭沒(méi)有 - )
    

    數(shù)組的項(xiàng)通過(guò) - 表示

  • toml寫(xiě)法:

    desc = ["red", false, { color = "red", age = 1 }]
    
    desc = [
      "red", 
      false, 
      { 
        color = "red", 
        age = 1 
      }
    ]
    

    空白會(huì)被忽略,子元素由逗號(hào)分隔,合規(guī)的類(lèi)型都可以作為值,可以混合不同類(lèi)型的值

2?? JSON數(shù)組多級(jí)嵌套的的基本用法

  • json寫(xiě)法:

    {
      "animals": [
        {
          "desc": [
            "red",
            false,
            1
          ]
        },
        {
          "dog": [
            {
              "color": "black",
              "age": 1
            },
            {
              "color": "white",
              "age": 2
            }
          ],
          "cat": [
            {
              "color": "black",
              "age": 3
            }
          ]
        }
      ]
    }
    
  • json寫(xiě)法:

    animals:
      - desc:
        - red
        - false
        - 1
      - dog:
        - color: black
          age: 1
        - color: white
          age: 2
        cat:
        - color: black
          age: 3
    
  • toml寫(xiě)法:

    [[animals]]
    desc = ["red",false,1]
    
    [[animals.dog]]
    color = "black"
    age = 1
    
    [[animals.dog]]
    color = "white"
    age = 2
    
    [[animals.cat]]
    color = "black"
    age = 3
    

    數(shù)組在toml中稱(chēng)為表數(shù)組,它通過(guò)把表名寫(xiě)在雙方括號(hào)里的表頭來(lái)表示([[animals]]

    表頭的第一例定義了這個(gè)數(shù)組及其首個(gè)表元素,而后續(xù)的每個(gè)則在該數(shù)組中創(chuàng)建并定義一個(gè)新的表元素。這些表按出現(xiàn)順序插入該數(shù)組

    注意和對(duì)象的區(qū)別,表是一個(gè)括號(hào)表示 [desc],表數(shù)組是雙方括表示 [[animals]]

數(shù)組與嵌套數(shù)組小結(jié)

其實(shí)作為配置文件來(lái)說(shuō),數(shù)組一般還是有不少使用場(chǎng)景的,對(duì)于掌握數(shù)組的基本用法還是蠻有必要的,但是,對(duì)于類(lèi)JSON數(shù)組來(lái)說(shuō),使用場(chǎng)景比較有限(gtHub action配置文件中這種用法多一些)。

竟然覺(jué)得JOSN看著屬于比較清晰、易讀的;yaml寫(xiě)法我在配置github action的時(shí)候使用過(guò),當(dāng)時(shí)就是語(yǔ)法縮進(jìn)和數(shù)組對(duì)象結(jié)構(gòu)一起使用時(shí)犯了錯(cuò),耽誤了不少時(shí)間定位問(wèn)題,還是那句話,yaml對(duì)于縮進(jìn)的處理需要特別注意;toml我用著還是不太習(xí)慣,但是總體結(jié)構(gòu)劃分、讀寫(xiě)性上絕對(duì)值得點(diǎn)贊,看著還是比較清晰地,就是對(duì)于表的使用需要適應(yīng),用習(xí)慣了覺(jué)得是值得推薦的。

總結(jié)

好了,就寫(xiě)這么多吧。對(duì)于相關(guān)內(nèi)容感興趣的可以去官方文檔進(jìn)一步查看,本文也只是通用功能的概括,篇幅有限,很多高級(jí)用法這里不再贅述。

其實(shí),這整個(gè)一輪學(xué)習(xí)、分析對(duì)比下來(lái),就這三種配置文件格式來(lái)說(shuō),如果沒(méi)有特殊使用場(chǎng)景,到了一定需要考慮選擇配置文件的地方,我覺(jué)得吧,就JS對(duì)象用著就挺好的,畢竟人家webpack這么多配置,用著不也是完全ok;但是這樣說(shuō)是屬于比較局限于前端角度的看法,畢竟我們對(duì)于JS語(yǔ)言整體是熟悉的,上手起來(lái)自然容易些。

但是,作為配置文件來(lái)說(shuō),它一定不能像開(kāi)發(fā)語(yǔ)言一樣那么的重,其實(shí)也不需要那么多功能,我們對(duì)配置文件的定位就是,它只要能覆蓋我們基本的使用場(chǎng)景也就足夠了。

資料

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容