JSON Schemaパターンサンプル
JSON拡張項目の設定方法
Kurocoのコンテンツ定義では、JSON型の拡張項目を使って柔軟なフォームUIを構築できます。 このページでは、実際に使えるJSON Schemaのパターンを紹介します。
Kurocoで使用するJSONスキーマの構文は、https://json-schema.org/understanding-json-schema/basics に準拠しています。 基本的な構文については公式仕様を参照してください。
基本的なフィールドタイプ
セレクトボックス(文字列の選択)
{
"type": "object",
"properties": {
"status": {
"type": "string",
"title": "ステータス",
"description": "コンテンツの公開状態を選択してください",
"enum": ["draft", "published", "archived"],
"default": "draft"
}
}
}
表示: セレクトボックス
ステータス *
[draft ▼] ← デフォルト値が選択される
- draft
- published
- archived
コンテンツの公開状態を選択してください
注意: defaultが設定されている場合はその値が初期選択されます。
セレクトボックス(表示ラベルのカスタマイズ)
{
"type": "object",
"properties": {
"priority": {
"type": "string",
"title": "優先度",
"enum": ["low", "medium", "high", "urgent"],
"enumNames": ["低", "中", "高", "緊急"],
"default": "medium"
}
}
}
表示: セレクトボックス(日本語ラベル)
優先度
[中 ▼] ← デフォルト値("medium")が選択される
- 低 (value: "low")
- 中 (value: "medium")
- 高 (value: "high")
- 緊急 (value: "urgent")
注意: enumNamesを使用することで、内部的な値(lowなど)とは異なる表示ラベル(低など)を設定できます。
セレクトボックス(数値の選択)
{
"type": "object",
"properties": {
"rating": {
"type": "integer",
"title": "評価",
"enum": [1, 2, 3, 4, 5],
"enumNames": ["★", "★★", "★★★", "★★★★", "★★★★★"]
}
}
}
表示: セレクトボックス(数値)
評価
[★ ▼] ← デフォルトで最初の値(1)が選択される
- ★ (value: 1)
- ★★ (value: 2)
- ★★★ (value: 3)
- ★★★★ (value: 4)
- ★★★★★ (value: 5)
注意: Number/Integer型のenumの場合、default未設定時は最初の値が自動選択されます。
複数選択セレクトボックス
{
"type": "object",
"properties": {
"tags": {
"type": "array",
"title": "タグ",
"description": "複数選択可能です(Ctrl/Cmd + クリック)",
"items": {
"type": "string",
"enum": ["技術", "ビジネス", "デザイン", "マーケティング", "その他"]
}
}
}
}
表示: 複数選択セレクトボックス
タグ
[複数選択可能なリスト]
□ 技術
□ ビジネス
□ デザイン
□ マーケティング
□ その他
複数選択可能です(Ctrl/Cmd + クリック)
実用的な入力フォーム
ファイルマネージャー(画像・ファイル選択)
{
"type": "object",
"title": "メディア設定",
"properties": {
"thumbnailImage": {
"type": "string",
"title": "サムネイル画像",
"description": "一覧表示用のサムネイル画像を選択してください",
"format": "file-manager"
},
"headerImage": {
"type": "string",
"title": "ヘッダー画像",
"description": "ページ上部に表示する画像",
"format": "file-manager"
},
"pdfDocument": {
"type": "string",
"title": "PDFドキュメント",
"description": "ダウンロード用PDFファイル",
"format": "file-manager"
},
"videoFile": {
"type": "string",
"title": "動画ファイル",
"format": "file-manager"
}
}
}
表示:
サムネイル画像
[+ ファイルマネージャー] → CKFinder ウィンドウが開く
/files/user/images/thumbnail.jpg [× 削除]
一覧表示用のサムネイル画像を選択してください
ヘッダー画像
[+ ファイルマネージャー] → 既存ファイルを変更
/files/user/images/header.png [× 削除]
ページ上部に表示する画像
PDFドキュメント
[+ ファイルマネージャー]
未設定
ダウンロード用PDFファイル
動画ファイル
[+ ファイルマネージャー]
未設定
特徴:
- CKFinderとの完全統合
- ファイルパスを文字列として保存
- ファイル選択後にプレビューリンク表示
WYSIWYGエディタ(HTMLエディタ)
{
"type": "object",
"title": "記事コンテンツ",
"properties": {
"title": {
"type": "string",
"title": "タイトル",
"minLength": 1,
"maxLength": 100
},
"summary": {
"type": "string",
"title": "要約",
"description": "記事の簡単な説明(プレーンテキスト)",
"format": "textarea",
"rows": 3
},
"content": {
"type": "string",
"title": "本文",
"description": "記事の本文をHTML形式で入力してください",
"format": "html"
},
"sidebarContent": {
"type": "string",
"title": "サイドバーコンテンツ",
"description": "サイドバーに表示する内容",
"format": "html",
"wysiwyg_height": 200,
"wysiwyg_width": "100%"
}
}
}
表示:
タイトル *
[テキスト入力]
要約
[テキストエリア(3行)]
記事の簡単な説明(プレーンテキスト)
本文 *
[CKEditor - WYSIWYGエディタ]
├─ ツールバー: 太字、斜体、リンク、画像、リストなど
├─ ファイルマネージャー統合(画像アップロード可能)
└─ HTMLソース編集可能
記事の本文をHTML形式で入力してください
サイドバーコンテンツ
[CKEditor - WYSIWYGエディタ(高さ200px)]
サイドバーに表示する内容
特徴:
format: "html"でCKEditorを自動表示wysiwyg_height: エディタの高さ指定(ピクセル単位)wysiwyg_width: エディタの幅指定(ピクセルまたはパーセンテージ)- CKFinderとの完全統合(画像アップロード・管理)
日付・日時の入力
{
"type": "object",
"title": "日付・日時設定",
"properties": {
"publishDate": {
"type": "string",
"title": "公開日",
"description": "記事を公開する日付を選択してください",
"format": "date",
"nullable": false
},
"publishDateTime": {
"type": "string",
"title": "公開日時",
"description": "記事を公開する日時を選択してください",
"format": "date-time",
"nullable": false
},
"eventStartDate": {
"type": ["string", "null"],
"title": "イベント開始日(必須)",
"description": "イベントの開始日を選択してください",
"format": "date"
},
"eventEndDateTime": {
"type": ["string", "null"],
"title": "イベント終了日時(任意)",
"description": "イベントの終了日時を選択してください",
"format": "date-time"
}
}
}
表示例:
公開日
[DatePicker: 📅 YYYY/MM/DD]
記事を公開する日付を選択してください
公開日時
[DatePicker: 📅 YYYY/MM/DD HH:mm:ss]
記事を公開する日時を選択してください
イベント開始日(必須) *
[DatePicker: 📅 YYYY/MM/DD]
イベントの開始日を選択してください
イベント終了日時(任意)
[DatePicker: 📅 YYYY/MM/DD HH:mm:ss]
イベントの終了日時を選択してください
特徴:
format: "date": 日付のみ(年月日)を入力format: "date-time": 日付と時刻(年月日 時分秒)を入力nullable: false: 必須項目の表示を設定可能- DatePickerコンポーネントで直感的に選択
応用的な設定例
繰り返し項目(配列フォーム)
{
"type": "object",
"properties": {
"news": {
"type": "array",
"title": "ニュース一覧",
"description": "最新のニュースを最大10件まで登録できます",
"minItems": 1,
"maxItems": 10,
"items": {
"type": "object",
"properties": {
"title": {
"type": "string",
"title": "タイトル",
"description": "ニュースのタイトルを入力してください",
"maxLength": 100
},
"link": {
"type": "string",
"title": "リンク",
"description": "ニュース記事のURLを入力してください"
},
"publishDate": {
"type": ["string", "null"],
"title": "公開日",
"format": "date"
},
"category": {
"type": "string",
"title": "カテゴリー",
"enum": ["press", "blog", "event", "update"],
"enumNames": ["プレスリリース", "ブログ", "イベント", "アップデート"]
}
},
"required": ["title", "link"]
}
}
}
}
表示: 繰り返し可能なカードUI
ニュース一覧
[JSON プレビュー] ← クリックでJSON確認(モーダル表示)
最新のニュースを最大10件まで登録できます
┌─────────────────────────────────────────┐
│ ニュース一覧 #1 [↑][↓][× 削除] │
├─────────────────────────────────────────┤
│ タイトル * │
│ [テキスト入力] │
│ ニュースのタイトルを入力してください │
│ │
│ リンク * │
│ [テキスト入力] │
│ ニュース記事のURLを入力してください │
│ │
│ 公開日 │
│ [📅 DatePicker] │
│ │
│ カテゴリー │
│ [-- 選択してください -- ▼] │
│ - プレスリリース │
│ - ブログ │
│ - イベント │
│ - アップデート │
├─────────────────────────────────────────┤
│ [+ ニュース一覧を追加] │
└─────────────────────────────────────────┘
┌─────────────────────────────────────────┐
│ ニュース一覧 #2 [↑][↓][× 削除] │
├─────────────────────────────────────────┤
│ ... │
├─────────────────────────────────────────┤
│ [+ ニュース一覧を追加] │
└─────────────────────────────────────────┘
特徴:
- 各アイテムがカード形式で表示
- ↑↓ボタンで順番を入れ替え可能
- 各カードの下に「追加」ボタンを配置
minItems: 最低限必要なアイテム数(削除時に制限、アラート表示)maxItems: 最大登録可能数(追加時に制限、アラート表示)- JSON プレビューボタンで確認可能(モーダル表示、読み取り専用)
- descriptionは各フィールドの下部に小さな文字で表示
ブログ記事の設定フォーム例
{
"type": "object",
"title": "ブログ記事設定",
"properties": {
"title": {
"type": "string",
"title": "記事タイトル",
"minLength": 1,
"maxLength": 100
},
"category": {
"type": "string",
"title": "カテゴリー",
"enum": ["news", "tutorial", "blog", "announcement"],
"enumNames": ["ニュース", "チュートリアル", "ブログ", "お知らせ"]
},
"status": {
"type": "string",
"title": "公開状態",
"enum": ["draft", "review", "published", "archived"],
"enumNames": ["下書き", "レビュー待ち", "公開済み", "アーカイブ"],
"default": "draft"
},
"featured": {
"type": "boolean",
"title": "注目記事"
},
"tags": {
"type": "array",
"title": "タグ",
"items": {
"type": "string",
"enum": ["Vue.js", "React", "Angular", "JavaScript", "TypeScript", "CSS", "HTML"]
}
},
"visibility": {
"type": "string",
"title": "閲覧権限",
"enum": ["public", "members", "premium", "private"],
"enumNames": ["公開", "会員限定", "プレミアム会員限定", "非公開"],
"default": "public"
},
"publishDate": {
"type": ["string", "null"],
"title": "公開日",
"description": "記事を公開する日付を選択してください",
"format": "date"
},
"publishDateTime": {
"type": ["string", "null"],
"title": "公開日時",
"description": "記事を公開する日時を選択してください",
"format": "date-time"
}
},
"required": ["title", "category", "status"]
}
表示例:
記事タイトル *
[テキスト入力]
カテゴリー *
[セレクトボックス: ニュース / チュートリアル / ブログ / お知らせ]
公開状態 *
[セレクトボックス: 下書き / レビュー待ち / 公開済み / アーカイブ]
注目記事
☑ 有効にする
タグ
[複数選択: Vue.js / React / Angular / ...]
閲覧権限
[セレクトボックス: 公開 / 会員限定 / プレミアム会員限定 / 非公開]
公開日
[DatePicker: 📅 YYYY/MM/DD]
記事を公開する日付を選択してください
公開日時
[DatePicker: 📅 YYYY/MM/DD HH:mm:ss]
記事を公開する日時を選択してください
ECサイト商品設定例
{
"type": "object",
"title": "商品設定",
"properties": {
"productName": {
"type": "string",
"title": "商品名",
"minLength": 1
},
"size": {
"type": "string",
"title": "サイズ",
"enum": ["XS", "S", "M", "L", "XL", "XXL"]
},
"color": {
"type": "string",
"title": "カラー",
"enum": ["red", "blue", "green", "black", "white", "yellow"],
"enumNames": ["レッド", "ブルー", "グリーン", "ブラック", "ホワイト", "イエロー"]
},
"availability": {
"type": "string",
"title": "在庫状況",
"enum": ["in_stock", "low_stock", "out_of_stock", "pre_order"],
"enumNames": ["在庫あり", "残りわずか", "在庫切れ", "予約受付中"],
"default": "in_stock"
},
"shippingOptions": {
"type": "array",
"title": "配送方法",
"items": {
"type": "string",
"enum": ["standard", "express", "overnight", "pickup"],
"enumNames": ["通常配送", "速達", "翌日配送", "店舗受取"]
}
},
"price": {
"type": "number",
"title": "価格",
"minimum": 0
},
"onSale": {
"type": "boolean",
"title": "セール対象"
}
},
"required": ["productName", "price", "availability"]
}
表示例:
商品名 *
[テキスト入力]
サイズ
[セレクトボックス: XS / S / M / L / XL / XXL]
カラー
[セレクトボックス: レッド / ブルー / グリーン / ブラック / ホワイト / イエロー]
在庫状況 *
[セレクトボックス: 在庫あり / 残りわずか / 在庫切れ / 予約受付中]
配送方法
[複数選択: 通常配送 / 速達 / 翌日配送 / 店舗受取]
価格 *
[数値入力]
セール対象
☑ 有効にする
より複雑な配列例(商品バリエーション with WYSIWYG)
{
"type": "object",
"properties": {
"productVariants": {
"type": "array",
"title": "商品バリエーション",
"description": "サイズ・カラー別の商品情報を登録",
"minItems": 1,
"items": {
"type": "object",
"properties": {
"sku": {
"type": "string",
"title": "SKU",
"description": "商品コード"
},
"size": {
"type": "string",
"title": "サイズ",
"enum": ["XS", "S", "M", "L", "XL", "XXL"]
},
"color": {
"type": "string",
"title": "カラー",
"enum": ["red", "blue", "green", "black", "white"],
"enumNames": ["レッド", "ブルー", "グリーン", "ブラック", "ホワイト"]
},
"description": {
"type": "string",
"title": "商品説明",
"description": "このバリエーションの詳細説明",
"format": "html",
"wysiwyg_height": 300
},
"stock": {
"type": "integer",
"title": "在庫数",
"minimum": 0,
"default": 0
},
"price": {
"type": "number",
"title": "価格",
"minimum": 0
},
"image": {
"type": "string",
"title": "商品画像",
"format": "file-manager"
},
"available": {
"type": "boolean",
"title": "販売中",
"default": true
}
},
"required": ["sku", "size", "color", "price"]
}
}
}
}
特徴:
- 配列オブジェクト内で
format: "html"を使用してWYSIWYGエディタを配置可能 - 各アイテムごとに独立したCKEditorインスタンスが生成される
- ファイルマネージャーとWYSIWYGを同時に使用可能
wysiwyg_heightで各エディタの高さを個別に調整可能
設定リファレンス
表示モード
build_ui_from_schemaが有効 → JSON Schemaに基づいたフォームUIを表示build_ui_from_schemaが無効 → JSONエディタのみ表示
フィールドタイプの自動判定
string- テキスト入力string+enum- セレクトボックスstring+format: "date"- DatePicker(日付のみ)string+format: "date-time"- DatePicker(日時)string+format: "file-manager"- ファイルマネージャー(CKFinder統合)string+format: "html"- WYSIWYGエディタ(CKEditor)string+format: "textarea"- テキストエリアnumber/integer- 数値入力number/integer+enum- 数値セレクトボックスboolean- チェックボックスarray+items.type: "string"- カンマ区切りテキストエリアarray+items.enum- 複数選択セレクトボックスarray+items.type: "object"- 繰り返しカードUIobject- JSON形式テキストエリア
デフォルト値の決定
defaultが設定されている → その値を使用defaultが未設定の場合:enumにnullが含まれる →nullを初期値とするenumにnullが含まれない →enum[0](最初の値)を初期値とする
バリデーション
required- 必須項目(Array/Objectタイプ用)nullable- null許可(false時に必須マーク表示、Enum/Date/Number/Integer用)minLength/maxLength- 文字数制限(String用、minLength: 1で必須マーク表示)minimum/maximum- 数値範囲minItems/maxItems- 配列要素数制限pattern- 正規表現パターン
必須項目の設定方法
フィールドを必須項目にする方法は、フィールドタイプによって異なります。
Enum、Date、Date-time、Number、Integerの場合
{
"type": "string", // または "integer", "number"、nullを許可しない
"format": "date", // または "enum": ["1", "2"],
"nullable": false // ← これがfalseの場合に必須マーク表示
}
ルール: nullable: false を設定すると必須マーク(*)が表示されます。typeでnullを許可しないことで入力必須にします。
String(テキスト入力)の場合
{
"type": "string",
"minLength": 1 // ← これが1以上の場合に必須マーク表示
}
ルール: minLength: 1 以上を設定すると必須項目になり、必須マーク(*)が表示されます。
Array(配列)、Object(オブジェクト)の場合
{
"type": "object",
"properties": {
"tags": {
"type": "array",
"minItems": 1, // ← 1つ以上選択必須
"items": {
"type": "string",
"enum": ["1", "2", "3"]
}
}
},
"required": ["tags"] // ← required配列に含まれる場合に必須マーク表示
}
ルール: スキーマのトップレベルにあるrequired配列にフィールド名を含めると必須表示になります。
実践例: 複数タイプの必須項目を含むスキーマ
{
"type": "object",
"properties": {
"status": {
"type": "string", // ← "null"を許可しない
"enum": [null, "draft", "published"],
"nullable": false // ← 必須マーク表示
},
"name": {
"type": "string",
"minLength": 1 // ← 必須マーク表示
},
"publishDate": {
"type": "string", // ← "null"を許可しない
"format": "date",
"nullable": false // ← 必須マーク表示
},
"tags": {
"type": "array",
"minItems": 1, // ← 1つ以上選択必須
"items": {
"type": "string",
"enum": ["1", "2", "3"]
}
}
},
"required": ["tags"] // ← Array/Object以外は各プロパティの設定で必須判定される
}
配列オブジェクトUIの動作
- アイテム追加時に
maxItemsチェック(上限に達している場合はアラート表示) - アイテム削除時に
minItemsチェック(最小数を下回る場合はアラート表示) - 各カード下部に「追加」ボタンを配置
- アイテムがゼロの場合は最初の「追加」ボタンのみ表示
その他の機能
enumNamesで表示ラベルをカスタマイズ可能type: ["string", "null"]のようなUnion Type(nullable)に対応descriptionはフィールド下部にヘルプテキストとして表示- JSON プレビューボタンで現在の値を確認可能(モーダル表示)
ネスト構造の対応状況と制限
サポートされているネスト構造
システムは以下のネスト構造に対応しています:
Object (単一オブジェクト)
{
"type": "object",
"properties": {
"name": {"type": "string"},
"email": {"type": "string"}
}
}
Array → Object (オブジェクトの配列)
{
"type": "array",
"items": {
"type": "object",
"properties": {
"title": {"type": "string"},
"link": {"type": "string"}
}
}
}
Object → Array → Object (オブジェクト内の配列内のオブジェクト)
{
"type": "object",
"properties": {
"news": {
"type": "array",
"items": {
"type": "object",
"properties": {
"title": {"type": "string"},
"category": {"type": "string", "enum": ["blog", "news"]}
}
}
}
}
}
解説: これらのパターンは完全にサポートされており、UIで直接編集可能です。
制限事項: Array → Object → Array → Object
4階層以上のネスト構造(Array → Object → Array → Object)は、現在UIでの直接編集に対応していません。
対応していない例
{
"type": "object",
"properties": {
"departments": {
"type": "array",
"title": "部署一覧",
"items": {
"type": "object",
"properties": {
"departmentName": {"type": "string", "title": "部署名"},
"employees": {
"type": "array",
"title": "社員一覧",
"items": {
"type": "object",
"properties": {
"employeeName": {"type": "string", "title": "社員名"},
"skills": {
"type": "array",
"title": "スキル一覧",
"items": {
"type": "object",
"properties": {
"skillName": {"type": "string"}
}
}
}
}
}
}
}
}
}
}
}
問題点: departments (Array) → employees (Object → Array) → skills (Object → Array) のような4階層構造は、繰り返しUIの中に繰り返しUIがネストされるため、現在対応していません。
推奨される回避策: 構造を分割する
深いネスト構造が必要な場合は、複数の拡張項目に分割することで対応できます。
解決例: 2つの拡張項目に分割
拡張項目1: departments_data (部署と社員情報)
{
"type": "object",
"properties": {
"departmentId": {
"type": "string",
"title": "部署ID",
"description": "一意の部署識別子"
},
"departmentName": {
"type": "string",
"title": "部署名"
},
"employees": {
"type": "array",
"title": "社員一覧",
"items": {
"type": "object",
"properties": {
"employeeId": {
"type": "string",
"title": "社員ID"
},
"employeeName": {
"type": "string",
"title": "社員名"
},
"position": {
"type": "string",
"title": "役職",
"enum": ["manager","staff","intern"],
"enumNames": ["マネージャー","スタッフ","インターン"
]
}
}
}
}
}
}
拡張項目2: employee_skills_data (社員のスキル情報)
{
"type": "object",
"properties": {
"employeeId": {
"type": "string",
"title": "社員ID",
"description": "departments_dataの社員IDと対応"
},
"employeeName": {
"type": "string",
"title": "社員名(参照用)"
},
"employeeSkills": {
"type": "array",
"title": "社員スキル一覧",
"items": {
"type": "object",
"properties": {
"skillName": {
"type": "string",
"title": "スキル名"
},
"level": {
"type": "string",
"title": "習熟度",
"enum": ["beginner","intermediate","advanced","expert"],
"enumNames": ["初級","中級","上級","エキスパート"]
},
"yearsOfExperience": {
"type": "integer",
"title": "経験年数",
"minimum": 0
}
}
}
}
}
}
メリット:
- ✅ 各拡張項目が3階層以内(Object → Array → Object)に収まる
- ✅ UIで完全に編集可能
- ✅
employeeIdをキーとしてデータを関連付け - ✅ それぞれのデータを独立して管理できる
データの関連付け:
departments_dataで社員の基本情報を管理employee_skills_dataで社員のスキル情報を管理- 両者を
employeeIdで紐付け
ネスト構造の対応表
| 構造パターン | 階層数 | UI対応 | 例 |
|---|---|---|---|
| Object | 1階層 | ✅ | {type: "object"} |
| Array → Object | 2階層 | ✅ | ニュース一覧、商品バリエーション |
| Object → Array → Object | 3階層 | ✅ | ユーザー情報 → 注文履歴 |
| Array → Object → Array → Object | 4階層 | ❌ | 部署 → 社員 → スキル |
| それ以上の深いネスト | 5階層以上 | ❌ | - |
サポート
お探しのページは見つかりましたか?解決しない場合は、問い合わせフォームからお問い合わせいただくか、Slackコミュニティにご参加ください。