什么是YAML?语法、数据类型、用途和陷阱
无爬虫抓取API以JSON或CSV返回结构化网页数据,当需要人工编辑的配置边界时,受控管道可以将其转换为YAML。
简言之
- YAML是一种面向人类的数据序列化语言。 它使用缩进和有限的标点符号表示映射、序列和标量值。
- YAML在配置文件中很常见。 注释、可读的键、块字符串和紧凑的列表使其在源控制中方便进行设置审查。
- 空格有助于保持结构。 空格建立嵌套,而制表符处理和不一致的缩进可能会导致错误或意外的数据。
- 解析器行为必须受到控制。 YAML版本、模式、标签、重复键和隐式类型可以改变文本如何转换为应用程序值。
- YAML并不适合每条数据路径。 JSON通常对API更清晰,而类型化的二进制或列式格式对大型分析数据集更好。
YAML是什么意思?
YAML意味着'YAML不是标记语言'。它是一种基于Unicode的数据序列化语言,旨在与常见编程结构清晰映射。YAML文档由三种主要节点类型构成:用于键值关联的映射、用于有序集合的序列,以及用于单独值的标量。
的 YAML 1.2.2规范 描述了表示模型、序列化树、展示流、语法、标签和模式。YAML的展示层提供了几种编写等效数据的方式,这有助于人类作者,但给实现者比JSON更少的语法选择。
YAML是数据,根据定义不是指令语言。应用程序经常使用它来配置部署、构建系统、自动化作业、静态网站元数据和本地开发工具。应用程序决定哪些键是有效的以及这些键的作用。
基本YAML语法
YAML配置可以结合映射、序列、数字、布尔值和嵌套值:
service:
name: catalog-worker
enabled: true
workers: 4
regions:
- us-east
- eu-west
output:
format: json
include_metadata: true
冒号将映射键与其值分开。破折号以块样式引入序列项。缩进放置 name, enabled,其余的设置放置在 service。该文档在此样式下无需大括号或逗号。
映射
映射将键与值关联。键通常是简单字符串,尽管语言模型允许更复杂的键。配置作者应该优先选择简单、唯一的字符串键,因为应用程序库和验证工具可以可预测地处理它们。
重复的映射键是可移植性问题。库可能会拒绝它们,保留一个值,或暴露受选项控制的行为。生产配置加载器应拒绝重复,以便审查员和运行的应用程序看到相同的有效设置。
序列
序列是有序的。块样式每个项使用一个破折号,而流样式使用方括号:
regions: [us-east, eu-west]
checks:
- name: schema
required: true
- name: links
required: true
每个项可以是标量、映射或另一个序列。只有在应用程序合同赋予其含义时,才应使用顺序。
标量和引用
标量包括字符串、数字、布尔值、空值、某些模式下的时间戳,以及带有显式标签的值。普通标量省略引号,但标点符号和某些单词可能在不同的YAML版本或解析器模式下以意想不到的方式解释。当文本形式必须保持准确(包括版本号、带前导零的标识符,以及类似布尔值或空值的字符串)时,请引用值。
单引号字符串大部分字符按字面意思处理。双引号字符串支持转义序列。块标量使用 | 来保持换行符或 > 将行折叠为空格,附加指示符控制缩进和尾部换行符。
注释、锚、别名和标签
哈希字符以外的引号标量开始注释。注释使YAML对配置变得有吸引力,因为维护者可以解释设置存在的原因。注释是展示的一部分,而不是核心数据模型的一部分,因此许多解析器在加载和写入文档时会舍弃它们。
锚标记节点,别名在其他地方引用该节点。这可以减少重复的配置:
defaults: &defaults
timeout_seconds: 30
output: json
jobs:
catalog:
<<: *defaults
region: us-east
此处显示的合并键被广泛使用,但合并行为并不是每个YAML处理路径的简单通用特性。确认所选库和应用程序支持的内容。过多的锚图也使得配置审查更困难,因为有效值不再在一个地方可见。
标签标识节点的类型或解释。标准标签覆盖字符串、整数、映射、序列和其他核心值。一些库支持特定于应用程序的标签,构造语言对象。将不受信任的标签加载到对象构造函数中可能是危险的;请使用安全加载器,将构造限制为预期的数据类型。
YAML模式与版本差异
YAML模式决定标量文本如何解析为标签。版本和模式差异解释了在配置仓库中发现的许多令人惊讶的示例。一个处理模式将某个词解释为布尔值,而在另一个处理模式下可能仍然是字符串。数字语法和时间戳处理也可能有所不同。
YAML 1.2将其JSON模式对齐,以便JSON文档在预期的兼容性模型中是有效的YAML。但这并不意味着每个YAML文件都是有效的JSON:注释、未引用的键、块集合、锚、别名和标签是YAML特性,而不属于JSON语法。
的 YAML媒体类型规范 注册 application/yaml 和 +yaml 结构语法后缀。仅凭文件扩展名并不能表明解析器架构或应用程序合同。项目应指定解析器库,记录所支持的YAML版本或子集,并根据应用程序架构验证加载的数据。
YAML与JSON
| 维度 | YAML | JSON |
|---|---|---|
| 主要优势 | 人为编写的配置和可读的结构化文档 | 可预测的机器交换和Web APIs |
| 结构 | 缩进、块样式或流样式 | 大括号、方括号、逗号和带引号的属性名 |
| 注释 | 支持 | 不是标准JSON的一部分 |
| 引用 | 锚和别名 | 没有原生引用语法 |
| 解析表面 | 广泛的语法与架构、标签和多种表现样式 | 更小的语法和更少的表现选择 |
| 常见文件使用 | 设置、清单、构建和部署配置 | API有效载荷、事件、应用程序状态、配置 |
| 流记录 | 支持多文档流,但应用程序约定各异 | 需要如数组或NDJSON这样的框架 |
常见YAML用例
应用程序配置
可读的嵌套设置、注释和列表在开发人员检查版本控制中的更改时效果良好。
基础设施清单
声明性系统使用YAML来描述所需资源、政策、关系和部署参数。
自动化管道
构建和交付工具通常使用YAML列出阶段、作业、依赖关系、环境和条件。
文档前言
静态网站和出版工具在人工撰写内容旁边放置小的YAML映射,以声明标题、标签和布局选项。
YAML安全性和可靠性
不可信的YAML应被视为不可信的结构化输入。使用安全加载模式,仅构建普通数据值,而不是特定于语言的对象或应用程序类。一般风险属于更广泛的类别,描述为 CWE-502: 反序列化不可信数据.
限制输入大小、嵌套深度、别名和汇总展开。小文档可以多次引用锚定值,导致加载器创建一个更大的内存结构。库提供不同的控制,因此测试应在具有代表性的限制下测试已部署的解析器。
在解析后验证加载的数据。当配置错误可能危险时,拒绝未知的顶级键。检查必需字段、允许的枚举值、数字范围、路径限制和设置之间的关系。在验证错误时,不要记录机密或完整配置。
常见YAML错误
- 使用制表符进行缩进。 优先使用空格,并通过编辑器设置和格式化器强制统一的缩进宽度。
- 留下模糊的标量未引用。 引用标识符和类似于布尔值、null、数字或时间戳的文本。
- 允许重复的键。 配置加载器或代码检查工具以拒绝它们。
- 假设评论能够保留在往返过程中。 许多基于对象的加载器丢弃评论和原始格式。
- 过度使用锚和合并。 重用可以减少重复,但隐藏的有效值使审查和覆盖变得困难。
- 跳过模式验证。 一个格式良好的文档仍然可能包含拼写错误的键或不安全的值。
如何正确使用YAML
- 定义一个小的支持子集。 决定项目是否允许锚、合并键、自定义标签、多文档流和流式样式。
- 固定解析器和行为。 记录库、支持的YAML版本、重复键政策和安全加载模式。
- 添加代码检查和模式检查。 在部署之前运行它们,以便缩进错误和未知的键能够尽早失败。
- 将秘密保存在未提交的YAML外部。 根据应用的文档机制引用环境提供的值或秘密管理器的值。
- 审核有效配置。 当存在继承或合并时,提供一个命令,以呈现最终设置而不暴露秘密值。
- 当边界发生变化时使用另一种格式。 对于公共API,优先使用JSON,对于大型数据集,优先使用类型化分析格式。
结论
YAML是一种灵活的序列化语言,其可读的块样式使其在配置中尤为有用。它的便利性伴随更大的解释表面:缩进、模式、标签、锚、别名、重复键和解析器选项都可以影响加载的值。一个可靠的YAML工作流缩小了支持的特性集,使用安全加载,验证结果数据,并将人性化的配置与高容量的机器交换区分开。
准备构建结构化的配置工作流了吗?
使用Scrapeless Scraping API收集结构化网络数据,然后只转换您的配置合同允许的验证值。
今天注册并获得 5美元的免费信用 — 无需信用卡.
领取您的5美元信用 →常见问题
YAML是编程语言吗?
不,YAML是一种数据序列化语言。应用程序可以将YAML键解释为指令,但该行为属于应用程序,而不是YAML本身。
YAML是JSON的超集吗?
YAML 1.2被设计为JSON语法适应其兼容性模型,但真实的解析器支持和边缘情况取决于版本和实现。特定于YAML的语法不是有效的JSON。
为什么缩进在YAML中重要?
缩进定义了块样式YAML中的父子结构。更改空格可以将值移动到另一个映射或序列中,或使文档无效。
YAML可以包含注释吗?
是的,YAML支持以井号开头的注释,位于引号外的标量。许多解析器在加载和写入往返过程中丢弃注释。
从不可信源解析YAML安全吗?
不受信的YAML需要安全加载器、资源限制、禁用特定于应用的对象构造和模式验证。绝不要在不受信的输入上使用通用对象反序列化模式。