Help us understand the problem. What is going on with this article?

mdconf でドキュメントから JSON Schema を生成する

More than 1 year has passed since last update.

※ 「JSON Schema からドキュメントを生成する」ではなく,「ドキュメントから JSON Schema を生成する」です.

はじめに

SDD (Specification Driven Development) では,Swagger,RAML といった API 定義フォーマットや,JSON Schema といった JSON Object 定義フォーマットなどがよく利用されます.これらのフォーマットからコードジェネレートしつつ,ドキュメントも生成することで,仕様と実装の乖離がなくなるといったメリットがあります.

よく見かけるのは,JSON (YAML) をソースとして管理し,それから HTML ドキュメントを生成するようなものですが,エンジニア以外のステークホルダがいる環境で運用するにあたっては,HTML のホスティングサーバを用意したり,それをアップデートし続けるジョブを用意したりと少々面倒なこともあります.

そこで今回は,JSON からドキュメントを生成するのではなく,ドキュメントから JSON を生成する ことで,上記の解決を試みます.ドキュメントはマークダウンで記述します.GitHub などは,マークダウンを HTML に変換して表示してくれるので,記述したマークダウンそのものがドキュメントとなります.つまり,ドキュメントが生成物ではなくソースになるため,GitHub などでソース管理するだけで,常に最新のドキュメントを閲覧することができます.

mdconf を使って JSON にパースする

例として,以下のような JSON Schema を利用します.

user.json
{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "id": "user",
  "type": "object",
  "additionalproperties": "false",
  "required": [
    "id",
    "lastName",
    "firstName",
    "state"
  ],
  "properties": {
    "id": {
      "type": "number"
    },
    "lastname": {
      "type": "string"
    },
    "firstname": {
      "type": "string"
    },
    "state": {
      "type": "number",
      "enum": [
        "1",
        "2"
      ]
    }
  }
}

マークダウンをパースして JSON にするために, mdconf を使います.mdconf では,#- を用いてプロパティや値を表現します.これらのいずれも付いていない行はパースの対象外なので,自由に記述することができます.

以下は,上記の JSON Schema を生成するマークダウンを記述したものになります.

user.md
- $schema: http://json-schema.org/draft-04/schema#

- id: user

- type: object

- additionalProperties: false

# required

- id

- lastName

- firstName

- state

# properties

## id

user id

- type: number

## lastName

user's last name

- type: string

## firstName

user's first name

- type: string

## state

user state

- type: number

### enum

active

- 1

inactive

- 2

GitHub では,以下のように表示されます.スキーマ定義が見やすいドキュメントになっていますね.このドキュメントをメンテナンスしていくことになります.

mdconf.png

以下が,このマークダウンをコードで利用し,バリデーションをおこなう例です.mdconf により簡単にパースすることができます.

import fs from 'fs'
import path from 'path'
import isMyJsonValid from 'is-my-json-valid'
import parse from 'mdconf'
import assert from 'assert'

// マークダウンを読み込み, JSON にパース
const mdFilePath = path.resolve(__dirname, 'user.md')
const schema = parse(fs.readFileSync(mdFilePath, 'utf8').toString()))

const userData = { id: 1, lastName: 'Yamada', firstName: 'Taro', state: 1 }

// データが想定しているフォーマットかどうか検証
const validator = isMyJsonValid(schema)
assert(validator(userData), validator.errors)

おわりに

マークダウンで Schema 定義を記述することで,ドキュメントとして利用しつつ,かつコードからも直接利用することができるようになりました.少々アグレッシブではありますが,Swagger や RAML などでも汎用的に使える方法ですので,興味を持たれた方はぜひ試してみてください.

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした