yaml の使い方 — JavaScriptでYAMLをパース・生成する決定版ライブラリ
一言でいうと
yaml は、YAML形式の文字列をJavaScriptオブジェクトに変換(パース)したり、その逆(文字列化)を行うためのライブラリです。YAML 1.1/1.2の両方に対応し、コメントや空行の保持・編集まで可能な、JavaScript/TypeScript向けYAML処理の決定版パッケージです。
どんな時に使う?
- 設定ファイルの読み書き — アプリケーションの設定ファイル(
.yml/.yaml)をNode.jsで読み込んでオブジェクトとして扱いたいとき - YAMLベースのデータ変換 — CI/CD設定(GitHub Actions, Docker Composeなど)をプログラムで生成・編集したいとき
- コメント付きYAMLの編集 — 既存のYAMLファイルのコメントや書式を壊さずに、特定の値だけをプログラムで書き換えたいとき
インストール
# npm
npm install yaml
# yarn
yarn add yaml
# pnpm
pnpm add yaml
Note: この記事は
yaml@2.x(執筆時点で v2.8.3)を対象としています。v1系とはAPIが大きく異なります。
基本的な使い方
最もよく使うパターンは parse と stringify です。
import { parse, stringify } from 'yaml';
import fs from 'node:fs';
// --- YAML文字列 → JavaScriptオブジェクト ---
const yamlString = `
name: my-app
version: 1.0.0
dependencies:
- express
- yaml
settings:
port: 3000
debug: true
`;
const config = parse(yamlString);
console.log(config);
// {
// name: 'my-app',
// version: '1.0.0',
// dependencies: ['express', 'yaml'],
// settings: { port: 3000, debug: true }
// }
// --- JavaScriptオブジェクト → YAML文字列 ---
const obj = {
database: {
host: 'localhost',
port: 5432,
name: 'mydb',
},
features: ['auth', 'logging'],
};
const output = stringify(obj);
console.log(output);
// database:
// host: localhost
// port: 5432
// name: mydb
// features:
// - auth
// - logging
// --- ファイルの読み書き ---
const fileContent = fs.readFileSync('./config.yml', 'utf8');
const parsed = parse(fileContent);
parsed.settings.port = 8080;
fs.writeFileSync('./config.yml', stringify(parsed));
よく使うAPI — yaml の主要機能と使い方
1. parse() — YAML文字列をパース
import { parse } from 'yaml';
// 基本的なパース
const data = parse('key: value');
// { key: 'value' }
// スカラー値もパースできる
parse('3.14159'); // 3.14159
parse('true'); // true
parse('null'); // null
parse('~'); // null
// reviver(変換関数)を使う
const result = parse('count: "42"', (key, value) => {
if (key === 'count') return Number(value);
return value;
});
// { count: 42 }
// オプション指定(YAML 1.1モード)
const legacy = parse(yamlStr, { version: '1.1' });
2. stringify() — オブジェクトをYAML文字列に変換
import { stringify } from 'yaml';
// 基本的な文字列化
const yaml = stringify({ name: 'test', items: [1, 2, 3] });
// name: test
// items:
// - 1
// - 2
// - 3
// replacerで出力するキーをフィルタリング
const filtered = stringify(
{ name: 'app', secret: 'xxx', port: 3000 },
(key, value) => (key === 'secret' ? undefined : value)
);
// name: app
// port: 3000
// オプションでインデントや折り返しを制御
const formatted = stringify(obj, {
indent: 4, // インデント幅
lineWidth: 80, // 行の折り返し幅
defaultStringType: 'QUOTE_DOUBLE', // 文字列のデフォルトクォートスタイル
defaultKeyType: 'PLAIN',
});
// 複数行文字列のブロックスタイル制御
const withBlock = stringify({
script: 'echo "hello"\necho "world"\n',
});
// script: |
// echo "hello"
// echo "world"
3. parseDocument() / parseAllDocuments() — ドキュメントレベルの操作
コメントの保持やAST操作が必要な場合に使います。
import { parseDocument, parseAllDocuments } from 'yaml';
// コメント付きYAMLをパースして編集
const doc = parseDocument(`
# アプリケーション設定
name: my-app
version: 1.0.0 # セマンティックバージョニング
port: 3000
`);
// 値の取得
console.log(doc.get('name')); // 'my-app'
console.log(doc.get('port')); // 3000
// 値の変更(コメントは保持される)
doc.set('port', 8080);
doc.set('newKey', 'newValue');
console.log(doc.toString());
// # アプリケーション設定
// name: my-app
// version: 1.0.0 # セマンティックバージョニング
// port: 8080
// newKey: newValue
// 複数ドキュメント(---区切り)のパース
const multiYaml = `
---
name: doc1
---
name: doc2
`;
const docs = parseAllDocuments(multiYaml);
docs.forEach((d) => {
console.log(d.toJSON()); // { name: 'doc1' }, { name: 'doc2' }
});
4. Document — プログラムからYAMLドキュメントを構築
import { Document } from 'yaml';
// 新規ドキュメントの作成
const doc = new Document({ name: 'my-app', version: '2.0.0' });
// ドキュメントにコメントを追加
doc.commentBefore = ' 自動生成された設定ファイル';
// ノードレベルでコメントを付与
const nameNode = doc.contents?.get('name', true);
if (nameNode) {
nameNode.comment = ' アプリケーション名';
}
// ネストしたオブジェクトを追加
doc.set('database', doc.createNode({
host: 'localhost',
port: 5432,
}));
console.log(doc.toString());
// # 自動生成された設定ファイル
// name: my-app #アプリケーション名
// version: "2.0.0"
// database:
// host: localhost
// port: 5432
5. visit() — ASTノードの走査・変更
import { parseDocument, visit, isScalar } from 'yaml';
const doc = parseDocument(`
servers:
- host: dev.example.com
port: 3000
- host: staging.example.com
port: 3000
`);
// すべてのスカラーノードを走査して変換
visit(doc, {
Scalar(key, node) {
// ホスト名を一括置換
if (typeof node.value === 'string' && node.value.includes('example.com')) {
node.value = node.value.replace('example.com', 'mycompany.io');
}
},
});
console.log(doc.toString());
// servers:
// - host: dev.mycompany.io
// port: 3000
// - host: staging.mycompany.io
// port: 3000
// 型ガード関数も豊富に用意されている
import { isMap, isSeq, isPair, isAlias, isNode, isCollection } from 'yaml';
類似パッケージとの比較
| 特徴 | yaml | js-yaml | yamljs |
|---|---|---|---|
| YAML 1.2 対応 | ✅ | ✅(v4〜) | ❌ |
| YAML 1.1 対応 | ✅ | ✅ | ✅ |
| コメント保持・編集 | ✅ | ❌ | ❌ |
| AST操作 | ✅(充実) | ❌ | ❌ |
| TypeScript型定義 | ✅(同梱) | ✅(@types) | ❌ |
| 外部依存 | なし | なし | あり |
| yaml-test-suite 全パス | ✅ | ❌ | ❌ |
| メンテナンス状況(2024年) | 活発 | 低頻度 | 停滞 |
| 週間DL数 | 非常に多い | 非常に多い | 少ない |
選定の指針:
- コメントを壊さずにYAMLを編集したい → yaml 一択
- 単純なパース/文字列化だけでよい → yaml または js-yaml どちらでも可
- YAML仕様への準拠度を重視する → yaml が最も正確
注意点・Tips
1. YAML 1.1 と 1.2 の挙動の違いに注意
import { parse } from 'yaml';
// デフォルトは YAML 1.2
parse('on'); // 'on'(文字列)
parse('yes'); // 'yes'(文字列)
// YAML 1.1 では on/yes/off/no が真偽値として解釈される
parse('on', { version: '1.1' }); // true
parse('yes', { version: '1.1' }); // true
YAML 1.1時代の設定ファイル(Ansible等)を扱う場合は version: '1.1' を明示しましょう。
2. parse() はエラーをスローしない場合がある
yaml パッケージは壊れた入力でもできる限りパースを試みます。厳密なバリデーションが必要な場合は parseDocument() でエラーを確認してください。
import { parseDocument } from 'yaml';
const doc = parseDocument(untrustedInput);
if (doc.errors.length > 0) {
console.error('パースエラー:', doc.errors);
throw new Error('Invalid YAML');
}
if (doc.warnings.length > 0) {
console.warn('警告:', doc.warnings);
}
const data = doc.toJSON();
3. コメントを保持したい場合は parseDocument() を使う
parse() はプレーンなJavaScriptオブジェクトを返すため、コメント情報は失われます。コメントを保持して再出力したい場合は必ず parseDocument() を使いましょう。
4. 大きなファイルの処理
非常に大きなYAMLファイルを扱う場合は、低レベルAPIの Lexer / Parser / Composer を使ったストリーミング処理が可能です。
import { Composer, Parser } from 'yaml';
const parser = new Parser();
const composer = new Composer();
// トークンを段階的に処理
for (const token of parser.parse(hugeYamlString)) {
for (const doc of composer.next(token)) {
console.log(doc.toJSON());
}
}
for (const doc of composer.end()) {
console.log(doc.toJSON());
}
5. セキュリティ上の注意
YAMLには !!js/function のようなカスタムタグが存在しますが、yaml@2 ではデフォルトで安全なスキーマが使用されます。信頼できない入力に対してカスタムタグを有効にしないでください。
まとめ
yaml パッケージは、YAML仕様への準拠度・コメント保持・AST操作の充実度において、JavaScript/TypeScriptエコシステムで最も完成度の高いYAMLライブラリです。単純な parse / stringify から、コメントを壊さないドキュメント編集、ASTの走査・変換まで、YAMLに関するあらゆるユースケースをカバーします。設定ファイルの読み書きやCI/CD設定の自動生成など、YAMLを扱う場面では第一選択肢として検討してください。