メインコンテンツまでスキップ

JSON Schemaパターンサンプル

JSON拡張項目の設定方法

Kurocoのコンテンツ定義では、JSON型の拡張項目を使って柔軟なフォームUIを構築できます。 このページでは、実際に使えるJSON Schemaのパターンを紹介します。

備考

Kurocoで使用するJSONスキーマの構文は、https://json-schema.org/understanding-json-schema/basics がベースです。 基本的な構文についてはJSON Schemaのドキュメントを参照してください。

基本的なフィールドタイプ

セレクトボックス(文字列の選択)

{
"type": "object",
"properties": {
"status": {
"type": "string",
"title": "ステータス",
"description": "コンテンツの公開状態を選択してください",
"enum": ["draft", "published", "archived"],
"default": "draft"
}
}
}

表示: セレクトボックス Image from Gyazo

注意: defaultが設定されている場合はその値が初期選択されます。


セレクトボックス(表示ラベルのカスタマイズ)

{
"type": "object",
"properties": {
"priority": {
"type": "string",
"title": "優先度",
"enum": ["low", "medium", "high", "urgent"],
"enumNames": ["低", "中", "高", "緊急"],
"default": "medium"
}
}
}

表示: セレクトボックス(日本語ラベル) Image from Gyazo

注意: enumNamesを使用することで、内部的な値(lowなど)とは異なる表示ラベル(など)を設定できます。


セレクトボックス(数値の選択)

{
"type": "object",
"properties": {
"rating": {
"type": "integer",
"title": "評価",
"enum": [1, 2, 3, 4, 5],
"enumNames": ["★", "★★", "★★★", "★★★★", "★★★★★"]
}
}
}

表示: セレクトボックス(数値) Image from Gyazo

注意: Number/Integer型のenumの場合、default未設定時は最初の値が自動選択されます。


複数選択セレクトボックス

{
"type": "object",
"properties": {
"tags": {
"type": "array",
"title": "タグ",
"description": "複数選択可能です(Ctrl/Cmd + クリック)",
"items": {
"type": "string",
"enum": ["技術", "ビジネス", "デザイン", "マーケティング", "その他"]
}
}
}
}

表示: 複数選択セレクトボックス Image from Gyazo


実用的な入力フォーム

ファイルマネージャー(画像・ファイル選択)

{
"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"
}
}
}

表示: Image from Gyazo

特徴:

  • 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",
"format_options": { "height": 300 }
}
}
}

表示: Image from Gyazo

特徴:

  • format: "html" でCKEditorを自動表示
  • format_options でエディタのオプションを指定
  • 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"
}
}
}

表示例: Image from Gyazo

特徴:

  • 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 Image from Gyazo

特徴:

  • 各アイテムがカード形式で表示
  • ↑↓ボタンで順番を入れ替え可能
  • 各カードの下に「追加」ボタンを配置
  • 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"]
}

表示例: Image from Gyazo


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"]
}

表示例: Image from Gyazo


より複雑な配列例(商品バリエーション 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",
"format_options": { "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"]
}
}
}
}

表示例: Image from Gyazo

特徴:

  • 配列オブジェクト内でformat: "html"を使用してWYSIWYGエディタを配置可能
  • 各アイテムごとに独立したCKEditorインスタンスが生成される
  • ファイルマネージャーとWYSIWYGを同時に使用可能
  • format_optionsでエディタの高さを個別に調整可能

設定リファレンス

表示モード

  • JSONデータ定義からUIを構成するが有効 → JSON Schemaに基づいたフォームUIを表示
  • JSONデータ定義からUIを構成するが無効 → 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" - 繰り返しカードUI
  • object - JSON形式テキストエリア

デフォルト値の決定

  1. defaultが設定されている → その値を使用
  2. defaultが未設定の場合:
    • enumnullが含まれる → nullを初期値とする
    • enumnullが含まれない → 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対応
Object1階層{type: "object"}
Array → Object2階層ニュース一覧、商品バリエーション
Object → Array → Object3階層ユーザー情報 → 注文履歴
Array → Object → Array → Object4階層部署 → 社員 → スキル
それ以上の深いネスト5階層以上-

サポート

お探しのページは見つかりましたか?解決しない場合は、問い合わせフォームからお問い合わせいただくか、Slackコミュニティにご参加ください。