JSONスキーマジェネレーター
JSONを貼り付けて、自動的にJSON Schemaを生成します。
使い方
- JSONオブジェクトまたは配列を入力エリアに貼り付けます。
- オプションを有効化: 「required」配列または値からの「examples」を含めます。
- スキーマを生成をクリックして、JSON Schema(Draft 2020-12)を作成します。
- 生成されたスキーマをコピーまたはダウンロードします。
よくある質問
どのバージョンのJSON Schemaが生成されますか?
ジェネレーターは、最新の安定したドラフトであるJSON Schema Draft 2020-12(https://json-schema.org/draft/2020-12/schema)を生成します。
ネストされたオブジェクトと配列を処理しますか?
はい。ジェネレーターはネストされたオブジェクトと配列を再帰的に処理します。配列の場合、最初の要素からスキーマを推論します。
生成されたスキーマを編集できますか?
出力は出発点です。minLength、minimum、pattern、enumなどの制約を必要に応じて追加することができます。
JSON Schemaは何のためにあるか
JSON Schemaは、JSON文書がどのような形であるべきかを宣言的に記述する方法です。どのプロパティを持ち、それらのプロパティがどの型を保持し、何が必須で何が任意で、どの値が有効かを示します。XMLにとってのXSDや、データベースのテーブル定義に相当するJSON世界のものです。公式プロジェクトはjson-schema.orgにあります。
実世界で出会う場面:
- APIコントラクト。 OpenAPI 3.1(2021年2月リリース)はJSON Schemaを直接埋め込みます。現代のAPI仕様におけるあらゆるリクエスト本体とレスポンス本体はJSON Schemaの断片で記述されます。
- IDEの自動補完と検証。 VS Codeの
settings.json、プロジェクトのpackage.jsonとtsconfig.json、GitHub Actionsのworkflow.ymlファイルはすべて公開されたJSON Schemaに対して自動補完とlintを行います。 - サーバサイド検証。 Express、Fastify、Spring、Flask、FastAPI、EchoはすべてJSON Schemaバリデータ(AJV、jsonschema、fastjsonschema)と統合し、不正な形のリクエスト本体をビジネスロジックに到達する前に拒否します。
- コード生成。
quicktype、json-schema-to-typescript、datamodel-code-generatorのようなツールはスキーマをGoの構造体、TypeScriptの型、PythonのデータクラスやJavaのPOJOなどへ変換し、単一のソースから言語に依存しない型を提供します。 - ドキュメンテーション。 スキーマは公開するあらゆるJSON形のデータに対する機械可読なドキュメントを兼ねます。
実際に目にするドラフト
JSON Schemaの仕様は一連のドラフトとして公開されてきました。現在の安定版ドラフトは2020-12です(公式仕様ページより: "The current version is 2020-12")。出会う可能性のあるドラフト:
- Draft 4、古いが今も使われている; OpenAPI 3.0はJSON Schema Specification Wright Draft 00(非公式に Draft 5 と呼ばれることもある)の拡張サブセットを使っていました。Draft 4 に近いが同一ではありません。
- Draft 6、Draft 7、Draft 7(2018)は何年もの間プロダクションで支配的なドラフトであり、レガシーなツールでは今も非常によく見ます。
- Draft 2019-09、年月形式の識別子規約を使った最初のドラフト。レガシーの
definitionsキーワードと並んで$defsを導入しました。 - Draft 2020-12、現在の安定版ドラフトであり、このジェネレータが出力するもの。OpenAPI 3.1と整合しています。
迷ったら、あなたのバリデータに合うドラフトを選んでください。AJV(最も人気のあるJavaScriptバリデータ)は明示的なオプトインにより Draft 04、06、07、2019-09、2020-12 をサポートします。Pythonのjsonschemaも同様です。下流の消費者が何を望むか分からないなら、2020-12は新しい作業に対して安全な既定です。
組み込みの型
JSON SchemaはJSONの値の種類に対応する七つの基本型を記述します。
| 型 | JSON値 | よく使うキーワード |
|---|---|---|
string | "hello" | minLength、maxLength、pattern、format |
number | 42, 3.14 | minimum、maximum、exclusiveMinimum、multipleOf |
integer | 42 | numberの部分集合; 小数部なし。 |
boolean | true / false | 追加の制約なし。 |
null | null | 別個の型; nullが有効な場合に明示的にする。 |
array | […] | items、minItems、maxItems、uniqueItems |
object | {…} | properties、required、additionalProperties |
構成キーワードを使えば組み合わせ自由です: oneOf(ちょうど一つ)、anyOf(少なくとも一つ)、allOf(全部)、not(逆)。さらに、許可される値の有限リスト用のenum、固定値一つ用のconst。
自動生成スキーマが教えてくれること、教えてくれないこと
単一のJSON例からスキーマを推定するのは強力ですが限界があります。ジェネレータが検出できるもの:
- あらゆる末端値の型(文字列、数値、ブール、配列、オブジェクトのいずれか)。
- ネストされたオブジェクトと配列の構造。
- 例に出現するキー(オプトインした場合は
requiredとして印を付ける)。
検出できないもの:
- 任意のフィールド。 あなたの例にあるキーが実際の仕様では任意かもしれませんが、単一の例ではどれがそうか分かりません。既定ではすべてが必須に見えます。
- フォーマットのヒント。 文字列
"2024-04-12"は日付のように見えますが、たまたま日付の形をした自由テキストのラベルかもしれません。本当に日付なら、format: dateを手で追加してください。 - 検証制約。 最大長、許可するenum値、正規表現パターン: いずれも人間の入力が必要です。
- ドキュメンテーション文字列。 各フィールドの
title、description、examplesは開発者体験を向上させますが、キュレーションが必要です。 - バリエーション。 あるフィールドが文脈次第で文字列にも数値にもなりうる場合、単一の例はどちらか一方を選び、もう片方を取りこぼします。複数の例を組み合わせるか、手動で
oneOfを使ってください。
出力は70%完成のスタート地点として扱ってください。価値のある追加(どのフィールドが本当に必須か、どの文字列フォーマットが当てはまるか、どの値の範囲が許されるか、各フィールドの意味)は人の手によるキュレーションの段階です。
知っておく価値のある二つの微妙な落とし穴
formatは2020-12では既定で助言的です。 format-annotation 語彙はformat: emailをヒントとして扱い、あなたのバリデータが明示的にformat-assertionをオプトインしない限り厳格な検証規則ではありません。したがってメールの正規表現にマッチしない文字列も既定では通過します。AJVのstrictモードとajv-formatsパッケージは完全なフォーマット検証を追加します。セキュリティ上重要な入力のフォーマットチェックに頼る前に、バリデータの既定値を確認してください。additionalProperties: falseはallOfとうまく協調しません。 継承スタイルの検証のためにallOfでスキーマを構成すると、ある枝のadditionalProperties: falseは兄弟枝で定義されたプロパティを見ないため、正当なフィールドが検証に失敗します。Draft 2019-09以降の解決策は構成を意識したunevaluatedProperties: falseです。
JSON Schema 対 Zod / Joi / Yup 対 TypeScript型
JSON Schemaの役割と重なる技術はいくつかあり、それぞれに得意分野があります。
- JSON Schema。 宣言的なJSON、実行時の検証、言語非依存。Go のサーバー、Python のデータパイプライン、TypeScript のフロントエンドが同じAPIを消費するなど、APIコントラクトが言語の境界を越える場面で強みを発揮します。
- TypeScriptの型。 コンパイル時のみ。TSコードベース内のプロセス内型安全には美しいが、実行時には消えてしまい、受信したJSONの検証は提供しません。
json-schema-to-typescriptのようなツールは、スキーマから型を生成して両方の良いとこどりを実現します。 - Zod、Joi、Yup。 JavaScriptやTypeScriptでのコードファースト実行時検証、TypeScript推論を組み込み。単一言語ですが、その言語内では優れた開発者体験を提供します。スキーマはJSオブジェクトであり、移植可能なJSONではありません。
- PydanticやMarshmallow。 Pythonでの相当物: Pythonの型ヒントによるクラスベースの実行時検証。
スキーマを複数の言語またはツール(IDE、OpenAPI ツーリング、コードジェネレータ)が消費する必要があるなら、JSON Schemaが正しい居場所です。単一の言語の中に留まるのであれば、その言語ネイティブの選択肢の方が書き心地が良いことが多いです。
よくあるユースケース
- OpenAPI仕様のブートストラップ。 実際のAPIレスポンスを貼り付け、スキーマを生成し、
components.schemasに入れる。 - TypeScript、Go、Pythonの型を生成する、
quicktypeなどを使い、単一のソースから言語に依存しない型を提供する。 - 信頼できない入力を検証する、AJV、jsonschema、Pydanticでサーバエンドポイント上で。
- IDE自動補完を書く、カスタム設定形式のために。VS Code、JetBrains のIDEなどはJSON Schemaを読んでJSONファイルの自動補完を実現します。
- 設定ファイルの形を文書化する、下流の消費者向けに。
- データ形式間の移行。 あるソースから生成されたJSON Schemaは下流での検証、変換、文書化を駆動できます。
よくある間違い
- 自動生成されたスキーマを最終仕様として扱う。 あくまでスタート地点です。フォーマットのヒントを追加し、本当に任意のフィールドに印を付け、ドキュメントを追加し、値の範囲を設定してください。
$schema宣言を忘れる。 バリデータはどのドラフトを適用するか知るためにこれを使います。常にスキーマの最上部に含めてください。requiredをプロパティごとの属性として扱う。 XSDやMongooseのスキーマと異なり、JSON Schemaのrequiredは必須プロパティの名前を列挙した、親オブジェクトレベルの配列です。- 厳格な検証が欲しいときに
additionalProperties: falseを忘れる。 既定値はtrueで、未知のキーが黙って許されることになります。 enumとexamplesを混同する。enum=許可される値のリスト(検証)。examples=ドキュメント目的のサンプル値(検証への影響なし)。formatが強制されると仮定する。 Draft 2020-12では既定で注釈であり、アサーションではありません。あなたのメール用正規表現はオプトインしない限り実行されません。- 単一の例から任意性を推定する。 例にあるすべてのキーは既定で必須になります。実際の仕様にはほとんど常に任意フィールドがあります。キュレーションの一部として
required配列から外してください。
その他のよくある質問
スキーマはOpenAPI 3.1で動きますか?
はい。OpenAPI 3.1(2021年2月リリース)はスキーマ言語をJSON Schema Draft 2020-12と完全に整合させました。これがこのジェネレータが出力するものです。スキーマをOpenAPI ドキュメントのcomponents.schemasに入れ、$refで参照してください。古い OpenAPI 3.0はそれ以前のサブセットを使っていました。3.0をターゲットにするなら調整が必要かもしれません。
このスキーマから自分の言語の型を生成できますか?
はい。quicktypeはJSON SchemaからTypeScript、Go、Python、Java、C#、Swift、Kotlin、Rust、Elmなどを生成します。json-schema-to-typescriptはJS専用の代替です。最も現代的な言語にはスキーマから型へのツールが少なくとも一つあります。生成されたスキーマはそのすべての入力として機能します。
$defsとdefinitionsの違いは何ですか?
どちらもドキュメント内の他の場所から$refできる再利用可能なサブスキーマを置く場所です。definitionsは古い名前で、Draft 04、06、07で使われました。$defsは現在の名前で、Draft 2019-09で導入され2020-12でも継続しています。機能的には等価ですが、新しい作業には$defsを使ってください。
私のJSONはどこかへ送られますか?
いいえ。スキーマ生成は完全にブラウザ内で動きます。貼り付けられたJSONはローカルで解析され、走査され、出力テキストエリアにスキーマとして出力されます。サーバにアップロードされず、記録されず、タブを閉じた後に保持されません。JSONの例には顧客記録、内部APIのレスポンス、従業員情報のような、第三者を通したくない実データが含まれることが多いため、これは重要です。
なぜ私の配列のスキーマは最初の要素だけを記述したのですか?
単一の例からの推定は配列を同質として扱います。最初の要素を見て、残りも同じだと仮定します。実際の配列が異なる形を持ちうるなら、itemsを{ "oneOf": [...] }として手書きする必要があります。あるいは各バリアントに対して別々にジェネレータを実行し、スキーマを組み合わせてください。
そもそもジェネレータを使うべきか、それともスキーマを手書きすべきか?
あなたが端から端まで管理する小さなスキーマなら、手書きの方が仕様を早く覚えられます。何十ものネストされたオブジェクトを持つ大きなAPIレスポンスでは、生成すれば数秒でドラフトに到達でき、節約した時間を制約、説明、required配列のキュレーションに使えます。働く多くの開発者は両方を行います: 生成して、それからキュレートする。