在 TypeScript 中使用 YAML:数据解析、生成与验证
YAML(YAML Ain't Markup Language)是最流行的数据序列化格式之一,广泛应用于配置文件、DevOps(Docker、Kubernetes、Ansible)以及 CI/CD 流水线中。在 TypeScript 生态系统中,使用 js-yaml 库来处理 YAML,该库完全支持 YAML 1.2 规范,包括复杂结构、标签和自定义数据类型。
安装与配置
首先,通过 npm 安装该库及其类型定义:
npm install js-yamlnpm install --save-dev @types/js-yaml安装完成后,您可以在 TypeScript 项目中导入该库:
import * as yaml from 'js-yaml';import * as fs from 'fs';在 TypeScript 中解析 YAML
读取 YAML 的主要函数是 yaml.load(),它将 YAML 字符串转换为 JavaScript/TypeScript 对象。以下是一个配置文件的示例:
// config.yaml// server:// port: 3000// host: "localhost"// database:// url: "mongodb://localhost:27017/mydb"// poolSize: 10// features:// - logging// - authentication
interface Config { server: { port: number; host: string; }; database: { url: string; poolSize: number; }; features: string[];}
const yamlContent = fs.readFileSync('config.yaml', 'utf8');const config = yaml.load(yamlContent) as Config;
console.log(config.server.port); // 3000console.log(config.features); // ['logging', 'authentication']为了安全解析(不执行代码),请使用 yaml.load()——它比 yaml.eval() 更安全,因为后者可能会执行任意 JavaScript 代码。
从 TypeScript 对象生成 YAML
反向操作——将 TypeScript 对象转换为 YAML 字符串——由 yaml.dump() 函数完成。这对于动态创建配置文件非常有用:
interface DeploymentConfig { apiVersion: string; kind: string; metadata: { name: string; labels?: Record<string, string> }; spec: { replicas: number; selector: Record<string, string> };}
const deployment: DeploymentConfig = { apiVersion: 'apps/v1', kind: 'Deployment', metadata: { name: 'my-app', labels: { app: 'my-app', tier: 'backend' } }, spec: { replicas: 3, selector: { matchLabels: { app: 'my-app' } } }};
const yamlString = yaml.dump(deployment, { indent: 2, lineWidth: 120, noRefs: true, sortKeys: true});
console.log(yamlString);// apiVersion: apps/v1// kind: Deployment// metadata:// labels:// app: my-app// tier: backend// name: my-app// spec:// replicas: 3// selector:// matchLabels:// app: my-app使用自定义类型
js-yaml 库支持自定义模式和数据类型。这在处理日期、正则表达式或特殊对象时特别有用:
import * as yaml from 'js-yaml';
// 创建日期的自定义类型const DateType = new yaml.Type('!date', { kind: 'scalar', resolve: (data: string) => !isNaN(Date.parse(data)), construct: (data: string) => new Date(data), instanceOf: Date, represent: (date: Date) => date.toISOString()});
// 创建支持标准类型和自定义类型的模式const schema = yaml.DEFAULT_SCHEMA.extend([DateType]);
const yamlWithDates = `event: !date 2024-12-25T10:00:00Ztitle: "圣诞研讨会"`;
const parsed = yaml.load(yamlWithDates, { schema });console.log(parsed.event instanceof Date); // trueconsole.log(parsed.event.toLocaleDateString('zh-CN')); // 2024/12/25