フロントエンド・エンジニアのためのYAML入門 第1回 YAMLの基本的な使い方:コレクション

フロントエンド・エンジニアのためのYAML入門です。シリーズを通して、基本的な仕様とその使い方について解説します。YAMLにはデータ更新などでふれるだけという方も、この機会に仕様からおさえましょう。

発行

著者 國仲 義則 フロントエンド・エンジニア
フロントエンド・エンジニアのためのYAML入門 シリーズの記事一覧

YAMLとは

YAMLは「YAML Ain't Markup Language」の略で、人間が読み書きしやすい構造化データを扱う仕様です。拡張子は.yamlまたは.ymlです。

YAML自体は仕様なので、各プログラミング言語でYAMLを扱うための実装が必要となります。JavaScriptの場合はYAMLを扱うためのライブラリとしてjs-yamlが存在します。

フロントエンド開発のみを行っている場合、もしかするとYAMLファイルを扱う機会がなかった方もいるかもしれません。しかし、YAML Frontmatterという形では目にしたことがあるのではないでしょうか。Markdownファイルなどの先頭に書かれている次のようなデータです。

---
title: あなたの素晴らしい記事
description: これまでにない、まったく新しい発想により生み出された記事
date: 2020-01-23
tags:
  - 人気トップ10
  - おすすめ

このデータをJSONで表そうとすると、次のようになります。

JSON形式のデータ

{
  "title": "あなたの素晴らしい記事",
  "description": "これまでにない、まったく新しい発想により生み出された記事",
  "date": "2020-01-23",
  "tags": [
    "人気トップ10",
    "おすすめ"
  ]
}

このような単純なデータの場合は読みやすさに大きな違いはありませんが、データ項目に" "が必要ないなど、どちらが書きやすいかといえば、YAMLのほうが書きやすいと思う方もいるのではないでしょうか。

今回のシリーズでは、このようにヒューマンフレンドリーな*YAMLの基本的な部分を解説していきます。

*注:ヒューマンフレンドリーな

YAMLの公式サイトでは、この仕様を次のように特徴づけています。

YAML is a human friendly data serialization standard for all programming languages.(YAMLはヒューマンフレンドリーな、すべてのプログラム言語のためのデータシリアル化の標準です)

YAMLはどこで使われているか

YAMLはどこで使われているでしょう。前述のとおり、YAML Frontmatterはよく見かけるものです。

また、GitHub ActionsやCIサービスの設定ファイルとしても利用されています。たとえば、ReactのリポジトリにはCircleCIの設定ファイルがあります*。これはYAMLで書かれています。

*注:ReactのCircleCI設定ファイル

フロントエンド開発の場面では、なんらかの静的データを扱いたいときに人間が編集しやすいように、JSONではなくYAMLを利用する場合があります。

YAMLのデータ構造

YAMLは主にコレクションスカラーという2つのデータ構造からなります。コレクションはシーケンスとマッピングをまとめたものです。

  • コレクション
    • シーケンス
    • マッピング
  • スカラー

正確には違いますが、無理やりJavaScriptで言い換えると、シーケンスは配列、マッピングは名前と値のペアの集まり、つまりkey: valueで表現する連想配列、スカラーはプリミティブです。実際の使用場面では、これらを組み合わせて使うことになるでしょう。

以降の仕様解説は、YAMLとJSONを併記してみます。YAMLに慣れていない人は直感的にわかりにくいと思いますが、JSONを合わせて見ることで、わかりやすくなるかもしれません。

シーケンスの書き方

配列を扱うシーケンスは、-(ハイフン)を使って表します。同じ階層にあるものが、同じ配列の要素となります。

YAMLのシーケンス

- a
- b
- c
  - d-1
  - d-2

JSONの配列

[
  "a",
  "b",
  "c",
  [
    "d-1",
    "d-2"
  ]
]

上記コードのようにインデントで入れ子構造を作ることもできます。

マッピングの書き方

連想配列を扱うマッピングでは、:(コロン)を使ってkey: valueを表します。

YAMLのマッピング

first: 1
second: 2
third: 3
twenty:
  twenty one: 21
  twenty two: 22

JSONのオブジェクト

{
  "first": 1,
  "second": 2,
  "third": 3,
  "twenty": {
    "twenty one": 21,
    "twenty two": 22
  }
}

冒頭でも少し触れましたが、マッピングのおもしろいところは、キー名にtwenty oneなどのように、スペースが入っていてもクォーテーションで囲む必要がないことです。

スカラーの書き方

基本的には書きたいものをそのまま書けば、YAMLが自動的に型を判別します。スカラーの詳細は次回以降で解説しますが、次のような型が存在します。

  • 文字列
  • Null
  • 真偽値
  • 整数
  • 浮動小数点
  • タイムスタンプ
  • バイナリ
  • マージ

筆者としてはタイムスタンプを扱えるのが非常に便利であると考えています。たとえばJavaScriptでYAMLを扱うメジャーなライブラリ、js-yamlでは、タイムスタンプと判定された文字列は、自前でパースしなくともDateオブジェクトとして扱えるようになります。

次のコードはjs-yamlを使い、Node.js環境で日付を処理する例です。

js-yamlでタイムスタンプを処理した例

const yaml = require('js-yaml')

const timestamp = '2020-01-01'
const date = yaml.safeLoad(timestamp)
console.log(date.getFullYear()) // => 2020

YAMLデータを取り出し、「年」を表示させると2020という数値が取得できます。きちんとDateオブジェクトとして扱われていることがわかります。

ブロックスタイルとフロースタイル

YAMLにはブロックスタイルフロースタイルという、2種類の書き方があり、ここまではブロックスタイルで説明してきました。

それではフロースタイルとはどういう書き方なのかというと、JSONのようにシーケンスを[]、マッピングを{}を使って表す記述方式です。

以下の2つのシーケンスは同じものを表しています。

YAMLのシーケンス(ブロックスタイル)

- a
- b
- c
- 
  - d-1
  - d-2

YAMLのシーケンス(フロースタイル)

[a, b, c, [d-1, d-2]]

フロースタイルは1行で書いてありますが、1行でまとめて書く必要は必ずしもなく、改行しても問題ありません。

また、ブロックスタイルとフロースタイルは混在させることができますので、上記コードは次のように書くこともできます。

YAMLのシーケンス(ブロックスタイルとフロースタイルの混在)

- a
- b
- c
- [
    d-1,
    d-2,
  ]

マッピングのフロースタイルも同様です。

YAMLのマッピング(ブロックスタイル)

first: 1
second: 2
third: 3
twenty:
  twenty one: 21
  twenty two: 22

YAMLのマッピング(フロースタイル)

{
  first: 1,
  second: 2,
  third: 3,
  twenty: {
    "twenty one": 21,
    "twenty two": 22,
  }
}

フロースタイルの場合、キーにスペースがあるとうまくパースできませんので、クォーテーション(" ")で囲む必要があります。

どちらを選ぶかは場合によるでしょうが、混在パターンは入れ子になったシーケンスを1行で書きたい場合などに活躍するのではないでしょうか。

コメント

YAMLのコメントは#記号で行います。

#はいわゆる行コメントで、この記号以降は行末までコメントとして扱われます。コメントの始まりと終わりを指定するタイプのコメントはありません。

コメントの例

--- #ドラフト
title: あなたの素晴らしい記事 #要タイトル変更
description: これまでにない、まったく新しい発想により生み出された記事
date: 2020-01-23
tags:
  - 人気トップ10
  - おすすめ

YAMLディレクティブと区切りマーカー

YAMLディレクティブとは、YAMLのバージョンを指定する記述です。%記号に続けて指定します。

%YAML 1.2
---
"これはYAMLドキュメントです"

執筆現在の最新バージョンであるYAML 1.2では、YAMLディレクティブを明示しているデータと、記載されていないデータのどちらも受け入れるように定められています。記載されていない場合、YAML 1.2のデータであると推定されます。

YAMLデータでよく見かける---は、バージョンを明記していないYAMLディレクティブだと考えるとよいでしょう。

---を複数使うことにより、1つのファイルに複数のドキュメントを持つことができます。

playlog.yaml

---
name: John Smith
end: 2020-01-20T21:03:35
stage: 5
---
name: John Smith
end: 2020-01-20T19:00:27
stage: 3
---
name: John Smith
end: 2020-01-20T14:24:11
stage: 2

これを前述したjs-yamlを使い、Node.js環境で処理してみましょう。

js-yamlの出力結果

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

const log = yaml.safeLoadAll(fs.readFileSync('playlog.yaml', 'utf8'))
console.log(JSON.stringify(log))

// 出力結果
/*
[
  {
    "name": "John Smith",
    "end": "2020-01-20T21:03:35.000Z",
    "stage": 5
  },
  {
    "name": "John Smith",
    "end": "2020-01-20T19:00:27.000Z",
    "stage": 3
  },
  {
    "name": "John Smith",
    "end": "2020-01-20T14:24:11.000Z",
    "stage": 2
  }
]
*/

このように、同じキーがあっても違うデータとして扱うことができます。

また...でドキュメント終了を表すことができ、この区切りマーカーが出たら新しいYAMLディレクティブが出るまでもう一度パースするようになります。

playlog.yaml

---
name: John Smith
end: 2020-01-20T21:03:35
...
stage: 5
---
name: John Smith
end: 2020-01-20T19:00:27
...
stage: 3
---
name: John Smith
end: 2020-01-20T14:24:11
...
stage: 2

js-yamlの出力結果

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

const log = yaml.safeLoadAll(fs.readFileSync('playlog.yaml', 'utf8'))
console.log(JSON.stringify(log))

// 出力結果
/*
[
  {
    "name": "John Smith",
    "end": "2020-01-20T21:03:35.000Z"
  },
  {
    "stage": 5
  },
  {
    "name": "John Smith",
    "end": "2020-01-20T19:00:27.000Z"
  },
  {
    "stage": 3
  },
  {
    "name": "John Smith",
    "end": "2020-01-20T14:24:11.000Z"
  },
  {
    "stage": 2
  }
]
*/

...記号を使うことはほとんどないでしょうが、見かけても混乱しないように「このような記述がある」と知っておくとよいでしょう。

まとめ

今回はYAMLの基本的な記述方法を紹介しました。

ブロックスタイルのYAMLは読むのも書くのも非常にわかりやすく、手軽に始めることができます。JavaScriptでYAMLデータを扱うにはjs-yamlが必要になりますが、ある程度の大きさのデータを人間が編集するような場面では、JSONよりも効率的ではないでしょうか。

次回はスカラーの型を紹介します。