现代配置YAML对比JSON优势分析

目录
  • 出现背景
    • 精简了什么?
    • 增加了什么?
  • 使用场景
  • YAML 语法
    • 对象
    • 数组
    • 纯量
  • 高级操作
    • 字符串过长
    • 获取配置
    • 配置项复用

一直以来,前端工程中的配置大多都是 .js 文件或者 .json 文件,最常见的比如:

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

这些配置对前端非常友好,因为都是我们熟悉的 JS 对象结构。一般静态化的配置会选择 json 文件,而动态化的配置,涉及到引入其他模块,因此会选择 js 文件。

还有现在许多新工具同时支持多种配置,比如 Eslint,两种格式的配置任你选择:

  • .eslintrc.json
  • .eslintrc.js

后来不知道什么时候,突然出现了一种以 .yaml 或 .yml 为后缀的配置文件。一开始以为是某个程序的专有配置,后来发现这个后缀的文件出现的频率越来越高,甚至 Eslint 也支持了第三种格式的配置 .eslintrc.yml

既然遇到了,那就探索它!

下面我们从 YAML 的出现背景,使用场景,具体用法,高级操作四个方面,看一下这个流行的现代化配置的神秘之处。

出现背景

一个新工具的出现避免不了有两个原因:

旧工具在某些场景表现吃力,需要更优的替代方案旧工具也没什么不好,只是新工具出现,比较而言显得它不太好

YAML 这种新工具就属于后者。其实在 yaml 出现之前 js+json 用的也不错,也没什么特别难以处理的问题;但是 yaml 出现以后,开始觉得它好乱呀什么东西,后来了解它后,越用越喜欢,一个字就是优雅。

很多文章说选择 yaml 是因为 json 的各种问题,json 不适合做配置文件,这我觉得有些言过其实了。我更愿意将 yaml 看做是 json 的升级,因为 yaml 在格式简化和体验上表现确实不错,这个得承认。

下面我们对比 YAML 和 JSON,从两方面分析:

精简了什么?

JSON 比较繁琐的地方是它严格的格式要求。比如这个对象:

{
  name: 'ruims'
}

在 JSON 中以下写法通通都是错的:

// key 没引号不行
{
  name: 'ruims'
}
// key 不是 "" 号不行
{
  'name': 'ruims'
}
// value 不是 "" 号不行
{
  "name": 'ruims'
}

字符串的值必须 k->v 都是 "" 才行:

// 只能这样
{
  "name": "ruims"
}

虽然是统一格式,但是使用上确实有不便利的地方。比如我在浏览器上测出了接口错误。然后把参数拷贝到 Postman 里调试,这时就我要手动给每个属性和值加 "" 号,非常繁琐。

YAML 则是另辟蹊径,直接把字符串符号干掉了。上面对象的同等 yaml 配置如下:

name: ruims

没错,就这么简单!

除了 "" 号,yaml 觉得 {} 和 [] 这种符号也是多余的,不如一起干掉。

于是呢,以这个对象数组为例:

{
  "names": [{ "name": "ruims" }, { "name": "ruidoc" }]
}

转换成 yaml 是这样的:

names:
  - name: ruims
  - name: ruidoc

对比一下这个精简程度,有什么理由不爱它?

增加了什么?

说起增加的部分,最值得一提的,是 YAML 支持了 注释。

用 JSON 写配置是不能有注释的,这就意味着我们的配置不会有备注,配置多了会非常凌乱,这是最不人性化的地方。

现在 yaml 支持了备注,以后配置可以是这样的:

# 应用名称
name: my_app
# 应用端口
port: 8080

把这种配置丢给新同事,还怕他看不懂配了啥吗?

除注释外,还支持配置复用的相关功能,这个后面说。

使用场景

我接触的第一个 yaml 配置是 Flutter 项目的包管理文件 pubspec.yaml,这个文件的作用和前端项目中的 package.json 一样,用于存放一些全局配置和应用依赖的包和版本。

看一下它的基本结构:

name: flutter_demo
description: A new Flutter project.

publish_to: 'none'
version: 1.0.0

dependencies:
  cupertino_icons: ^1.0.2

dev_dependencies:
  flutter_lints: ^1.0.0

你看这个结构和 package.json 是不是基本一致?dependencies 下列出应用依赖和版本,dev_dependencies 下的则是开发依赖。

后来在做 CI/CD 自动化部署的时候,我们用到了 GitHub Action。它需要多个 yaml 文件来定义不同的工作流,这个配置可比 flutter 复杂的多。

其实不光 GitHub Action,其他流行的类似的构建工具如 GitLab CI/CD,circleci,全部都是齐刷刷的 yaml 配置,因此如果你的项目要做 CI/CD 持续集成,不懂 yaml 语法肯定是不行的。

还有,接触过 Docker 的同学肯定知道 Docker Compose,它是 Docker 官方的单机编排工具,其配置文件 docker-compose.yml 也是妥妥的 yaml 格式。现在 Docker 正是如日中天的时候,使用 Docker 必然免不了编排,因此 yaml 语法早晚也要攻克。

上面说的这 3 个案例,几乎都是现代最新最流行的框架/工具。从它们身上可以看出来,yaml 必然是下一代配置文件的标准,并且是前端-后端-运维的通用标准。

说了这么多,你跃跃欲试了吗?下面我们详细介绍 yaml 语法。

YAML 语法

介绍 yaml 语法会对比 json 解释,以便我们快速理解。

先看一下 yaml 的几个特点:

大小写敏感

  • 使用缩进表示层级关系
  • 缩进空格数不强制,但相同层级要对齐
  • # 表示注释

相比于 JSON 来说,最大的区别是用 缩进 来表示层级,这个和 Python 非常接近。还有强化的一点是支持了注释,JSON 默认是不支持的(虽然 TS 支持),这也对配置文件非常重要。

YAML 支持以下几种数据结构:

对象:json 中的对象数组:json 中的数组纯量:json 中的简单类型(字符串,数值,布尔等)

对象

先看对象,上一个 json 例子:

{
  "id": 1,
  "name": "杨成功",
  "isman": true
}

转换成 yaml:

id: 1
name: 杨成功
isman: true

对象是最核心的结构,key 值的表示方法是 [key]: ,注意这里冒号后面有个空格,一定不能少。value 的值就是一个纯量,且默认不需要引号。

数组

数组和对象的结构差不多,区别是在 key 前用一个 符号标识这个是数组项。注意这里也有一个空格,同样也不能少。

- hello
- world

转换成 JSON 格式如下:

["hello", "world"]

了解了基本的对象和数组,我们再来看一个复杂的结构。

众所周知,在实际项目配置中很少有简单的对象或数组,大多都是对象和数组相互嵌套而成。在 js 中我们称之为对象数组,而在 yaml 中我们叫 复合结构。

比如这样一个稍复杂的 JSON:

{
  "name": "杨成功",
  "isman": true,
  "age": 25,
  "tag": ["阳光", "帅气"],
  "address": [
    { "c": "北京", "a": "海淀区" },
    { "c": "天津", "a": "滨海新区" }
  ]
}

转换成复合结构的 YAML:

name: 杨成功
isman: true
age: 25
tag:
  - 阳光
  - 帅气
address:
  - c: 北京
    a: 海淀区
  - c: 天津
    a: 滨海新区

纯量

纯量比较简单,对应的就是 js 的基本数据类型,支持如下:

  • 字符串
  • 布尔
  • 数值
  • null
  • 时间

比较特殊的两个,null 用 ~ 符号表示,时间大多用 2021-12-21 这种格式表示,如:

who: ~
date: 2019-09-10

转换成 JS 后:

{
  who: null,
  date: new Date('2019-09-10')
}

高级操作

在 yaml 实战过程中,遇到过一些特殊场景,可能需要一些特殊的处理。

字符串过长

在 shell 中我们常见到一些参数很多,然后特别长的命令,如果命令都写在一行的话可读性会非常差。

假设下面的是一条长命令:

$ docker run --name my-nginx -d nginx

在 linux 中可以这样处理:

$ docker run \
 --name my-nginx \
 -d nginx

就是在每行后加 \ 符号标识换行。然而在 YAML 中更简单,不需要加任何符号,直接换行即可:

cmd: docker run
  --name my-nginx
  -d nginx

YAML 默认会把换行符转换成空格,因此转换后 JSON 如下,正是我们需要的:

{ "cmd": "docker run --name my-nginx -d nginx" }

然而有时候,我们的需求是保留换行符,并不是把它转换成空格,又该怎么办呢?

这个也简单,只需要在首行加一个 | 符号:

cmd: |
  docker run
  --name my-nginx
  -d nginx

转换成 JSON 变成了这样:

{ "cmd": "docker run\n--name my-nginx\n-d nginx" }

获取配置

获取配置是指,在 YAML 文件中定义的某个配置,如何在代码(JS)里获取?

比如前端在 package.json 里有一个 version 的配置项表示应用版本,我们要在代码中获取版本,可以这么写:

import pack from './package.json'
console.log(pack.version)

JSON 是可以直接导入的,YAML 可就不行了,那怎么办呢?我们分环境解析:

在浏览器中

浏览器中代码用 webapck 打包,因此加一个 loader 即可:

$ yarn add -D yaml-loader

然后配置 loader:

// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.ya?ml$/,
        type: 'json', // Required by Webpack v4
        use: 'yaml-loader'
      }
    ]
  }
}

在组件中使用:

import pack from './package.yaml'
console.log(pack.version)

在 Node.js 中

Node.js 环境下没有 Webpack,因此读取 yaml 配置的方法也不一样。

首先安装一个 js-yaml 模块:

$ yarn add js-yaml

然后通过模块提供的方法获取:

const yaml = require('js-yaml')
const fs = require('fs')

const doc = yaml.load(fs.readFileSync('./package.yaml', 'utf8'))
console.log(doc.version)

配置项复用

配置项复用的意思是,对于定义过的配置,在后面的配置直接引用,而不是再写一遍,从而达到复用的目的。

YAML 中将定义的复用项称为锚点,用& 标识;引用锚点则用 * 标识。

name: &name my_config
env: &env
  version: 1.0

compose:
  key1: *name
  key2: *env

对应的 JSON 如下:

{
  "name": "my_config",
  "env": { "version": 1 },
  "compose": { "key1": "my_config", "key2": { "version": 1 } }
}

但是锚点有个弊端,就是不能作为 变量 在字符串中使用。比如:

name: &name my_config
compose:
  key1: *name
  key2: my name is *name

此时 key2 的值就是普通字符串 _my name is *name_,引用变得无效了。

其实在实际开发中,字符串中使用变量还是很常见的。比如在复杂的命令中多次使用某个路径,这个时候这个路径就应该是一个变量,在多个命令中复用。

GitHub Action 中有这样的支持,定义一个环境变量,然后在其他的地方复用:

env:
  NAME: test
describe: This app is called ${NAME}

这种实现方式与 webpack 中使用环境变量类似,在构建的时候将变量替换成对应的字符串。

以上就是现代配置YAML对比JSON优势分析的详细内容,更多关于YAML对比JSON优势的资料请关注我们其它相关文章!

(0)

相关推荐

  • Python常用配置文件ini、json、yaml读写总结

    本文参考文章,出于学习目的,写本文. 开发项目时,为了维护一些经常需要变更的数据,比如数据库的连接信息.请求的url.测试数据等,需要将这些数据写入配置文件,将数据和代码分离,只需要修改配置文件的参数,就可以快速完成环境的切换或者测试数据的更新,常用的配置文件格式有ini.json.yaml等,下面简单给大家介绍下,Python如何读写这几种格式的文件. 1.ini格式 ini 即 Initialize ,是Windows中常用的配置文件格式,结构比较简单,主要由节(Section).键(key

  • golang解析yaml文件操作

    首先安装解析的第三方包: go get gopkg.in/yaml.v2 示例: package main import ( "os" "log" "fmt" "encoding/json" "gopkg.in/yaml.v2" ) type Config struct { Test Test `yaml:"test"` } type Test struct { User []strin

  • XML和YAML的使用方法

    最近处理一些配置文件,碰到了YAML格式的文件,因为之前没接触过此格式的文件,对于XML还比较熟悉一些.那么什么是YAML呢?它相比XML又有哪些优缺点呢?什么情况下用YAML呢?YAML怎么使用呢?在此做一个简单的总结吧.咱们就先从XML来说吧.相信XML大家都比较熟知吧.下面是我从网络上摘取的概念性的东西,大家可以看一下.在此就不多说了.更多的说一些基本用法.XML概述:可扩展标记语言 (Extensible Markup Language, XML) ,用于标记电子文件使其具有结构性的标记

  • python Yaml、Json、Dict之间的转化

    Json To Dict import json jsonData = '{"a":1,"b":2,"c":3,"d":4,"e":5}'; print(jsonData) print(type(jsonData)) text = json.loads(jsonData) print(text) print(type(text)) ####################### {"a"

  • 现代配置YAML对比JSON优势分析

    目录 出现背景 精简了什么? 增加了什么? 使用场景 YAML 语法 对象 数组 纯量 高级操作 字符串过长 获取配置 配置项复用 一直以来,前端工程中的配置大多都是 .js 文件或者 .json 文件,最常见的比如: package.json babel.config.js webpack.config.js 这些配置对前端非常友好,因为都是我们熟悉的 JS 对象结构.一般静态化的配置会选择 json 文件,而动态化的配置,涉及到引入其他模块,因此会选择 js 文件. 还有现在许多新工具同时支

  • SpringBoot入门原理及优势分析

    目录 1.springboot可以干嘛用? 2.Spring Boot 的优势: 3.Spring Boot 的使用 4.创建Handler类 5.创建启动类 1.springboot可以干嘛用? 通过 Spring Boot 可以快速构建⼀个基于 Spring 框架的 Java Application,简化配置,自动装配. JavaConfiguration ⽤ Java 类替代 XML 的配置⽅式. Spring Boot 对常⽤的第三⽅库提供了配置⽅案,可以很好地和 Spring 进⾏整合

  • vue配置请求本地json数据的方法

    本篇文章主要介绍了vue配置请求本地json数据的方法,分享给大家,具体如下: 在build文件夹下找到webpack.dev.conf.js文件,在const portfinder = require('portfinder')后添加 const express = require('express') const app = express() const appData = require('../data.json') // 加载本地json文件 const seller = appDa

  • vue新vue-cli3环境配置和模拟json数据的实例

    最近在研究学习vue,发现环境配置特麻烦,就是跟着文档步骤一步一步来,也会遇到各种想不到的坑,vue-cli3的配置比老的简洁了很多,与以往的配置也有所不同: 1.安装步骤以前是 npm install vue-cli -g 现在是: npm install -g @vue/cli 2.vue-cli2 新建项目 vue init webpack Vue-Project vuecli3新建项目,在你创建后会有一个保存当前配置的功能 vue create <project-name> vue-c

  • SpringBoot集成Druid配置(yaml版本配置文件)详解

    maven 配置 <!-- https://mvnrepository.com/artifact/com.alibaba/druid --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2.3</version> </dependency> <dependency&g

  • Python实现yaml与json文件批量互转

    目录 1. 安装yaml库 2. yaml转json 3. json转yaml 4. 批量将yaml与json文件互相转换 1. 安装yaml库 想要使用python实现yaml与json格式互相转换,需要先下载pip,再通过pip安装yaml库. 如何下载以及使用pip,可参考:pip的安装与使用,解决pip下载速度慢的问题 安装yaml库: pip install pyyaml 2. yaml转json 新建一个test.yaml文件,添加以下内容: A: hello: name: Mich

  • SpringBoot自动配置特点与原理详细分析

    目录 一.SpringBoot是什么 二.SpringBoot的特点(核心功能) 三.SpringBoot的自动配置原理 1. @SpringBootApplication 2. @SpringBootConfiguration 3. @EnableAutoConfiguration 4. @ComponentScan 四.核心原理图 五.常用的Conditional注解 一.SpringBoot是什么 Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Sprin

  • 阿里云盘对比百度网盘优势分析(阿里云盘邀请码、内测码获取方法) 原创

    阿里巴巴开始预告推出阿里云盘以后,很多小伙伴都在关注这个事情,作为一家非常有实力的IT互联网公司,这个重磅产品一定会改变目前市场中网盘的格局,由于更推出,并且注册通过激活码邀请码的方式,很多朋友都没有能够提前体验到这款产品,为了回馈小伙伴对我们的支持,我们通过渠道获取了珍贵的9个激活码,在文末免费分享给大家! 阿里云网盘官网 阿里云盘官网:https://www.aliyundrive.com/ 阿里云官网截图 阿里云盘免费空间多大 1.阿里云网盘app免费的容量空间是1TB,如果是开放会员的话

  • 数据类型和Json格式分析小结

    1. 前几天,我才知道有一种简化的数据交换格式,叫做yaml. 我翻了一遍它的文档,看懂的地方不多,但是有一句话令我茅塞顿开. 它说,从结构上看,所有的数据最终都可以分成三种类型: 第一种类型是scalar(标量),也就是一个单独的string(字符串)或数字(numbers),比如"北京"这个单独的词. 第二种类型是sequence(序列),也就是若干个相关的数据按照一定顺序并列在一起,又叫做array(数组)或List(列表),比如"北京,东京". 第三种类型是

随机推荐