spectral は OpenAPI、AsyncAPI、JSON Schema などの API ドキュメントを検証するためのツールです。
今回は spectral を使用して OpenAPI の required フィールドを検証するカスタム関数を作成する方法について解説します。
【今回防ぎたいケース】
components:
schemas:
Me:
type: object
required:
...
# typo により properties に存在しないフィールドが指定されてしまっている。
#
# build-in rulesets を extends した
# 『['spectral:oas', 'spectral:asyncapi', 'spectral:arazzo']』
# では防げない。
- bithday
properties:
...
birthday:
type: string
format: date
description: 誕生日。
[目次]
環境
本記事の内容は spectral v6 系での動作を想定しています。
# 動作確認した 2024/10/13 時点での spectral のバージョン。 $ npx @stoplight/spectral-cli --version 6.13.1
custom functions の作成方法
spectral では、カスタム関数を作成して独自の検証が可能です。
今回は『OpenAPI で required フィールドに記載があるが、properties にその値が存在しない』というケースを検証をする関数を作成してみます。
作成が必要なファイルの全貌
プロジェクトのルートディレクトリに spectral-functions フォルダを作成し、その中に validateRequiredProperties.js ファイルを作成します。
.
├── .spectral.yaml
├── examples
│ └── get-me.json
├── openapi.yml
└── spectral-functions
└── validateRequiredProperties.js
各ファイル、それぞれ以下のような内容を記載しています。
.spectral.yaml
---
# Custom ruleset for the Spectral linter.
#
# ref: https://meta.stoplight.io/docs/spectral/01baf06bdd05a-create-a-ruleset
extends: ['spectral:oas', 'spectral:asyncapi', 'spectral:arazzo']
# ref: ./spectral-functions/
functions: [validateRequiredProperties]
functionsDir: './spectral-functions'
rules:
invalid-required-field:
description: 'Required fields must exist in the properties.'
message: "The required field '{{value}}' does not exist in the properties."
severity: error
given: '$.components.schemas.*'
then:
function: 'validateRequiredProperties'
examples/get-me.json
{ "name": "Test User", "mail": "l.user@example.com", "birthday": "2000-01-01" }
openapi.yml
openapi: 3.0.0
info:
version: 0.1.0
title: sample API
description: sample
contact:
name: sample team
servers:
- url: 'http://localhost:8080'
description: 開発環境
tags:
- name: User
description: ユーザー情報に関するエンドポイント。
paths:
/me:
get:
summary: ユーザー情報取得
operationId: getMe
description: ログインユーザーの情報を取得する。
tags:
- User
responses:
'200':
description: ユーザー情報を返す。
content:
application/json:
schema:
$ref: '#/components/schemas/Me'
example:
$ref: './examples/get-me.json'
components:
schemas:
Me:
type: object
required:
- name
- mail
- birthday
properties:
name:
type: string
description: ユーザー名。
mail:
type: string
description: メールアドレス。
birthday:
type: string
format: date
description: 誕生日。
spectral-functions/validateRequiredProperties.js
export default (input, opts, context) => {
const { required, properties } = input;
if (!required || !properties) {
return;
}
const propertyNames = Object.keys(properties);
const results = [];
required.forEach((prop, index) => {
if (!propertyNames.includes(prop)) {
results.push({
message: `The required field '${prop}' does not exist in the properties.`,
path: [...context.path, 'required', index],
});
}
});
return results;
};
.spectral.yaml
.spectral.yaml は spectral に関する設定を管理するためのファイルで、今回は functions, functionsDir, rules の 3 つを変更しました。
validateRequiredProperties.js の実装
カスタム関数は『input, options, context』の3つの引数を取ります。
ドキュメントに思ったより情報が書いてあったのと, console.log で出力を確かめながら実装できるため、ここでの説明は割愛します。