JSONのデータを加工して、HTMLに整形してブラウザで閲覧したいというユースケースでJekyllを使ってみた。
JekyllはGitHub Pagesで使われている静的サイト生成ツールであり、プラグインの機構もある。また _data/
にjsonファイルを置くと、site.data としてテンプレートからアクセスできる。
これはプラグインでも同様で、例えば _data/samples.json
がある場合はrubyのコード内でも site.data['samples']
としてアクセスできる。
またGeneratorの機能を利用するとSiteオブジェクトのpagesにPageのインスタンスを追加することでページを追加することができる。これを利用して _data/samples.json
からページを生成したという内容です。
_data/samples.jsonは以下のようにitem_id
を含む配列です。
[ {"item_id":1,"somedata":"somedata 1"},
{"item_id":2,"somedata":"somedata 2"},
{"item_id":3,"somedata":"somedata 3"},
{"item_id":4,"somedata":"somedata 4"},
{"item_id":5,"somedata":"somedata 5"} ]
Generatorでは、これを利用して以下のようにデータからページを作成することができる。
module Jekyll
class SamplesDataGenerator < Generator
def generate(site)
if site.data.key?('samples')
site.data['samples'].each do |item|
site.pages << to_item_page(site, item)
end
end
end
def to_item_page(site, item)
id = item["item_id"]
page = PageWithoutAFile.new(site, site.source, '/samples', "#{id}.html")
page.data.update({ "layout" => "sample_item", "item_id" => id })
page
end
end
end
PageWithoutAFile というのは、Pageのサブクラスでフロントマッター部だけでレンダリングが完了するページ用のクラスで、今回のコードだと以下のようなフロントマッターだけのページを作成するのと同様のことをしている。
---
item_id: 1
layout: sample_item
---
レイアウト sample_item
ではitem_id
を元にページを生成している。1
---
layout: default
---
{% assign item = site.data.samples | find: 'item_id', page.item_id %}
<div>
<!-- HTML template HERE. -->
</div>
つまり SamplesDataGenerator#generate 後は、以下のフォルダ構成でビルドするのと同じことになる。
.
├── _data
│ └── samples.json
├── _layouts
│ └── sample_item.html
└── samples # このsamples/以下をGeneratorで作っている
├── 1.html
├── 2.html
├── 3.html
├── 4.html
└── 5.html
結果として、_data/samples.jsonの配列のそれぞれのオブジェクトをページにすることができた。表示上の加工はJekyllのテンプレート機能で変更することができる。
加工は事前にjqなどで行っておくことでHTML生成とは切り離して行うことができる。
感想
割とよかった。今回JSONは利用しているSaaS製品のAPIから取得/加工している。
SaaS側のUIで手が届かない痒いところ2をどうにかしたかったのだが、API経由でエンティティをJSONで取り出して加工する、それをJekyllで静的サイトとして生成することで快適にデータをみることができるようになった。
エクスポートした一括データを保管しておいても、実際に使用したくなった場合に使いにくい場合が多いが、静的サイトを構築できるようにしておけば後々どうにかなる安心感がある。
こういうのは需要がありそうだけど面倒くさいが、こういうユースケースにつかえる道具が増えた感じがある。
プロジェクト管理ツールからデータをエクスポートして静的サイト構築したいみたいな気持ちがある。
ちなみに話はかわるが、フロントマッターはYAMLが想定されているけど、JSONも含むので以下のような記述もできた。
---
{"item_id":1,"layout":"sample_item.html"}
---