Skip to main content

JSON Schema Pattern Samples

How to Configure JSON Extension Fields

Kuroco's content definition allows you to build flexible form UIs using JSON-type extended fields. This page introduces practical JSON Schema patterns that you can use.

info

The JSON Schema syntax used in Kuroco conforms to the specification described at https://json-schema.org/understanding-json-schema/basics . Please refer to the official specification for details on the basic syntax.

Basic Field Types

Select Box (String Selection)

{
"type": "object",
"properties": {
"status": {
"type": "string",
"title": "Status",
"description": "Please select the publication status of the content",
"enum": ["draft", "published", "archived"],
"default": "draft"
}
}
}

Display: Select box

Status *
[draft ▼] ← Default value is selected
- draft
- published
- archived
Please select the publication status of the content

Note: When default is set, that value will be initially selected.


Select Box (Custom Display Labels)

{
"type": "object",
"properties": {
"priority": {
"type": "string",
"title": "Priority",
"enum": ["low", "medium", "high", "urgent"],
"enumNames": ["Low", "Medium", "High", "Urgent"],
"default": "medium"
}
}
}

Display: Select box (with custom labels)

Priority
[Medium ▼] ← Default value ("medium") is selected
- Low (value: "low")
- Medium (value: "medium")
- High (value: "high")
- Urgent (value: "urgent")

Note: By using enumNames, you can set display labels (e.g., "Low") that differ from the internal values (e.g., low).


Select Box (Numeric Selection)

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

Display: Select box (numeric)

Rating
[★ ▼] ← First value (1) is automatically selected by default
- ★ (value: 1)
- ★★ (value: 2)
- ★★★ (value: 3)
- ★★★★ (value: 4)
- ★★★★★ (value: 5)

Note: For Number/Integer type enums, when default is not set, the first value is automatically selected.


Multi-Select Box

{
"type": "object",
"properties": {
"tags": {
"type": "array",
"title": "Tags",
"description": "Multiple selections possible (Ctrl/Cmd + click)",
"items": {
"type": "string",
"enum": ["Technology", "Business", "Design", "Marketing", "Other"]
}
}
}
}

Display: Multi-select box

Tags
[Multi-select list]
□ Technology
□ Business
□ Design
□ Marketing
□ Other
Multiple selections possible (Ctrl/Cmd + click)

Practical Input Forms

File Manager (Image/File Selection)

{
"type": "object",
"title": "Media Settings",
"properties": {
"thumbnailImage": {
"type": "string",
"title": "Thumbnail Image",
"description": "Please select a thumbnail image for list display",
"format": "file-manager"
},
"headerImage": {
"type": "string",
"title": "Header Image",
"description": "Image to display at the top of the page",
"format": "file-manager"
},
"pdfDocument": {
"type": "string",
"title": "PDF Document",
"description": "PDF file for download",
"format": "file-manager"
},
"videoFile": {
"type": "string",
"title": "Video File",
"format": "file-manager"
}
}
}

Display:

Thumbnail Image
[+ File Manager] → CKFinder window opens
/files/user/images/thumbnail.jpg [× Delete]
Please select a thumbnail image for list display

Header Image
[+ File Manager] → Change existing file
/files/user/images/header.png [× Delete]
Image to display at the top of the page

PDF Document
[+ File Manager]
Not set
PDF file for download

Video File
[+ File Manager]
Not set

Features:

  • Complete integration with CKFinder
  • Stores file path as string
  • Shows preview link after file selection

WYSIWYG Editor (HTML Editor)

{
"type": "object",
"title": "Article Content",
"properties": {
"title": {
"type": "string",
"title": "Title",
"minLength": 1,
"maxLength": 100
},
"summary": {
"type": "string",
"title": "Summary",
"description": "Brief description of the article (plain text)",
"format": "textarea",
"rows": 3
},
"content": {
"type": "string",
"title": "Body",
"description": "Please enter the article body in HTML format",
"format": "html"
},
"sidebarContent": {
"type": "string",
"title": "Sidebar Content",
"description": "Content to display in the sidebar",
"format": "html",
"wysiwyg_height": 200,
"wysiwyg_width": "100%"
}
}
}

Display:

Title *
[Text input]

Summary
[Textarea (3 rows)]
Brief description of the article (plain text)

Body *
[CKEditor - WYSIWYG editor]
├─ Toolbar: Bold, Italic, Link, Image, List, etc.
├─ File Manager integration (image upload available)
└─ HTML source editing available
Please enter the article body in HTML format

Sidebar Content
[CKEditor - WYSIWYG editor (height 200px)]
Content to display in the sidebar

Features:

  • format: "html" automatically displays CKEditor
  • wysiwyg_height: Specify editor height (in pixels)
  • wysiwyg_width: Specify editor width (pixels or percentage)
  • Complete integration with CKFinder (image upload & management)

Date and DateTime Input

{
"type": "object",
"title": "Date & Time Settings",
"properties": {
"publishDate": {
"type": "string",
"title": "Publication Date",
"description": "Please select the date to publish the article",
"format": "date",
"nullable": false
},
"publishDateTime": {
"type": "string",
"title": "Publication Date & Time",
"description": "Please select the date and time to publish the article",
"format": "date-time",
"nullable": false
},
"eventStartDate": {
"type": ["string", "null"],
"title": "Event Start Date (Required)",
"description": "Please select the event start date",
"format": "date"
},
"eventEndDateTime": {
"type": ["string", "null"],
"title": "Event End Date & Time (Optional)",
"description": "Please select the event end date and time",
"format": "date-time"
}
}
}

Display Example:

Publication Date
[DatePicker: 📅 YYYY/MM/DD]
Please select the date to publish the article

Publication Date & Time
[DatePicker: 📅 YYYY/MM/DD HH:mm:ss]
Please select the date and time to publish the article

Event Start Date (Required) *
[DatePicker: 📅 YYYY/MM/DD]
Please select the event start date

Event End Date & Time (Optional)
[DatePicker: 📅 YYYY/MM/DD HH:mm:ss]
Please select the event end date and time

Features:

  • format: "date": Date only (year, month, day)
  • format: "date-time": Date and time (year, month, day, hour, minute, second)
  • nullable: false: Can be set as required field display
  • Intuitive selection with DatePicker component

Advanced Configuration Examples

Repeating Fields (Array Forms)

{
"type": "object",
"properties": {
"news": {
"type": "array",
"title": "News List",
"description": "You can register up to 10 latest news items",
"minItems": 1,
"maxItems": 10,
"items": {
"type": "object",
"properties": {
"title": {
"type": "string",
"title": "Title",
"description": "Please enter the news title",
"maxLength": 100
},
"link": {
"type": "string",
"title": "Link",
"description": "Please enter the URL of the news article"
},
"publishDate": {
"type": ["string", "null"],
"title": "Publication Date",
"format": "date"
},
"category": {
"type": "string",
"title": "Category",
"enum": ["press", "blog", "event", "update"],
"enumNames": ["Press Release", "Blog", "Event", "Update"]
}
},
"required": ["title", "link"]
}
}
}
}

Display: Repeatable card UI

News List
[JSON Preview] ← Click to view JSON (modal display)

You can register up to 10 latest news items

┌─────────────────────────────────────────┐
│ News List #1 [↑][↓][× Delete] │
├─────────────────────────────────────────┤
│ Title * │
│ [Text input] │
│ Please enter the news title │
│ │
│ Link * │
│ [Text input] │
│ Please enter the URL of the news article │
│ │
│ Publication Date │
│ [📅 DatePicker] │
│ │
│ Category │
│ [-- Please select -- ▼] │
│ - Press Release │
│ - Blog │
│ - Event │
│ - Update │
├─────────────────────────────────────────┤
│ [+ Add News List] │
└─────────────────────────────────────────┘

┌─────────────────────────────────────────┐
│ News List #2 [↑][↓][× Delete] │
├─────────────────────────────────────────┤
│ ... │
├─────────────────────────────────────────┤
│ [+ Add News List] │
└─────────────────────────────────────────┘

Features:

  • Each item is displayed in card format
  • Reorder with ↑↓ buttons
  • "Add" button placed below each card
  • minItems: Minimum required items (restriction on deletion, alert displayed)
  • maxItems: Maximum items allowed (restriction on addition, alert displayed)
  • Verify with JSON Preview button (modal display, read-only)
  • description is displayed in small text below each field

Blog Article Settings Example

{
"type": "object",
"title": "Blog Post Settings",
"properties": {
"title": {
"type": "string",
"title": "Post Title",
"minLength": 1,
"maxLength": 100
},
"category": {
"type": "string",
"title": "Category",
"enum": ["news", "tutorial", "blog", "announcement"],
"enumNames": ["News", "Tutorial", "Blog", "Announcement"]
},
"status": {
"type": "string",
"title": "Publication Status",
"enum": ["draft", "review", "published", "archived"],
"enumNames": ["Draft", "Under Review", "Published", "Archived"],
"default": "draft"
},
"featured": {
"type": "boolean",
"title": "Featured Post"
},
"tags": {
"type": "array",
"title": "Tags",
"items": {
"type": "string",
"enum": ["Vue.js", "React", "Angular", "JavaScript", "TypeScript", "CSS", "HTML"]
}
},
"visibility": {
"type": "string",
"title": "Access Permissions",
"enum": ["public", "members", "premium", "private"],
"enumNames": ["Public", "Members Only", "Premium Members Only", "Private"],
"default": "public"
},
"publishDate": {
"type": ["string", "null"],
"title": "Publication Date",
"description": "Please select the date to publish the article",
"format": "date"
},
"publishDateTime": {
"type": ["string", "null"],
"title": "Publication Date & Time",
"description": "Please select the date and time to publish the article",
"format": "date-time"
}
},
"required": ["title", "category", "status"]
}

Display Example:

Post Title *
[Text input]

Category *
[Select box: News / Tutorial / Blog / Announcement]

Publication Status *
[Select box: Draft / Under Review / Published / Archived]

Featured Post
☑ Enable

Tags
[Multi-select: Vue.js / React / Angular / ...]

Access Permissions
[Select box: Public / Members Only / Premium Members Only / Private]

Publication Date
[DatePicker: 📅 YYYY/MM/DD]
Please select the date to publish the article

Publication Date & Time
[DatePicker: 📅 YYYY/MM/DD HH:mm:ss]
Please select the date and time to publish the article

E-Commerce Product Settings Example

{
"type": "object",
"title": "Product Settings",
"properties": {
"productName": {
"type": "string",
"title": "Product Name",
"minLength": 1
},
"size": {
"type": "string",
"title": "Size",
"enum": ["XS", "S", "M", "L", "XL", "XXL"]
},
"color": {
"type": "string",
"title": "Color",
"enum": ["red", "blue", "green", "black", "white", "yellow"],
"enumNames": ["Red", "Blue", "Green", "Black", "White", "Yellow"]
},
"availability": {
"type": "string",
"title": "Stock Status",
"enum": ["in_stock", "low_stock", "out_of_stock", "pre_order"],
"enumNames": ["In Stock", "Low Stock", "Out of Stock", "Pre-order Available"],
"default": "in_stock"
},
"shippingOptions": {
"type": "array",
"title": "Shipping Methods",
"items": {
"type": "string",
"enum": ["standard", "express", "overnight", "pickup"],
"enumNames": ["Standard Shipping", "Express", "Overnight", "Store Pickup"]
}
},
"price": {
"type": "number",
"title": "Price",
"minimum": 0
},
"onSale": {
"type": "boolean",
"title": "On Sale"
}
},
"required": ["productName", "price", "availability"]
}

Display Example:

Product Name *
[Text input]

Size
[Select box: XS / S / M / L / XL / XXL]

Color
[Select box: Red / Blue / Green / Black / White / Yellow]

Stock Status *
[Select box: In Stock / Low Stock / Out of Stock / Pre-order Available]

Shipping Methods
[Multi-select: Standard Shipping / Express / Overnight / Store Pickup]

Price *
[Numeric input]

On Sale
☑ Enable

Complex Array Example (Product Variations with WYSIWYG)

{
"type": "object",
"properties": {
"productVariants": {
"type": "array",
"title": "Product Variations",
"description": "Register product information by size and color",
"minItems": 1,
"items": {
"type": "object",
"properties": {
"sku": {
"type": "string",
"title": "SKU",
"description": "Product code"
},
"size": {
"type": "string",
"title": "Size",
"enum": ["XS", "S", "M", "L", "XL", "XXL"]
},
"color": {
"type": "string",
"title": "Color",
"enum": ["red", "blue", "green", "black", "white"],
"enumNames": ["Red", "Blue", "Green", "Black", "White"]
},
"description": {
"type": "string",
"title": "Product Description",
"description": "Detailed description of this variation",
"format": "html",
"wysiwyg_height": 300
},
"stock": {
"type": "integer",
"title": "Stock Quantity",
"minimum": 0,
"default": 0
},
"price": {
"type": "number",
"title": "Price",
"minimum": 0
},
"image": {
"type": "string",
"title": "Product Image",
"format": "file-manager"
},
"available": {
"type": "boolean",
"title": "For Sale",
"default": true
}
},
"required": ["sku", "size", "color", "price"]
}
}
}
}

Features:

  • WYSIWYG editor can be placed within array objects using format: "html"
  • Independent CKEditor instance is generated for each item
  • File Manager and WYSIWYG can be used simultaneously
  • Individual editor height adjustment with wysiwyg_height

Configuration Reference

Display Mode

  • build_ui_from_schema enabled → Display Form UI based on JSON Schema
  • build_ui_from_schema disabled → Display JSON Editor only

Automatic Field Type Detection

  • string - Text input
  • string + enum - Select box
  • string + format: "date" - DatePicker (date only)
  • string + format: "date-time" - DatePicker (date & time)
  • string + format: "file-manager" - File Manager (CKFinder integration)
  • string + format: "html" - WYSIWYG Editor (CKEditor)
  • string + format: "textarea" - Textarea
  • number / integer - Numeric input
  • number / integer + enum - Numeric select box
  • boolean - Checkbox
  • array + items.type: "string" - Comma-separated textarea
  • array + items.enum - Multi-select box
  • array + items.type: "object" - Repeating card UI
  • object - JSON format textarea

Default Value Determination

  1. If default is set → Use that value
  2. If default is not set:
    • If null is included in enum → Set null as initial value
    • If null is not included in enum → Set enum[0] (first value) as initial value

Validation

  • required - Required fields (for Array/Object types)
  • nullable - Allow null (display required mark when false, for Enum/Date/Number/Integer)
  • minLength / maxLength - Character limit (for String, minLength: 1 displays required mark)
  • minimum / maximum - Numeric range
  • minItems / maxItems - Array item count limit
  • pattern - Regular expression pattern

How to Set Required Fields

The method to make a field required differs by field type.

For Enum, Date, Date-time, Number, Integer

{
"type": "string", // or "integer", "number", do not allow null
"format": "date", // or "enum": ["1", "2"],
"nullable": false // ← Required mark displayed when this is false
}

Rule: Setting nullable: false displays the required mark (*). Making type not allow null makes input required.

For String (Text Input)

{
"type": "string",
"minLength": 1 // ← Required mark displayed when this is 1 or more
}

Rule: Setting minLength: 1 or higher makes it required and displays the required mark (*).

For Array, Object

{
"type": "object",
"properties": {
"tags": {
"type": "array",
"minItems": 1, // ← 1 or more selections required
"items": {
"type": "string",
"enum": ["1", "2", "3"]
}
}
},
"required": ["tags"] // ← Required mark displayed when included in required array
}

Rule: Including the field name in the top-level required array displays the required mark.

Practical Example: Schema with Multiple Required Field Types

{
"type": "object",
"properties": {
"status": {
"type": "string", // ← do not allow "null"
"enum": [null, "draft", "published"],
"nullable": false // ← Required mark displayed
},
"name": {
"type": "string",
"minLength": 1 // ← Required mark displayed
},
"publishDate": {
"type": "string", // ← do not allow "null"
"format": "date",
"nullable": false // ← Required mark displayed
},
"tags": {
"type": "array",
"minItems": 1, // ← 1 or more selections required
"items": {
"type": "string",
"enum": ["1", "2", "3"]
}
}
},
"required": ["tags"] // ← For non-Array/Object types, required is determined by property settings
}

Array Object UI Behavior

  • maxItems check when adding items (alert displayed when limit reached)
  • minItems check when deleting items (alert displayed when falling below minimum)
  • "Add" button placed below each card
  • Only the first "Add" button displayed when items are zero

Other Features

  • Display labels can be customized with enumNames
  • Supports Union Type (nullable) like type: ["string", "null"]
  • description is displayed as help text below the field
  • Current values can be verified with JSON Preview button (modal display)

Nested Structure Support and Limitations

✅ Supported Nested Structures

The system supports the following nested structures:

1. Object (Single Object)
{
"type": "object",
"properties": {
"name": {"type": "string"},
"email": {"type": "string"}
}
}
2. Array → Object (Array of Objects)
{
"type": "array",
"items": {
"type": "object",
"properties": {
"title": {"type": "string"},
"link": {"type": "string"}
}
}
}
3. Object → Array → Object (Object containing array of objects)
{
"type": "object",
"properties": {
"news": {
"type": "array",
"items": {
"type": "object",
"properties": {
"title": {"type": "string"},
"category": {"type": "string", "enum": ["blog", "news"]}
}
}
}
}
}

Explanation: These patterns are fully supported and directly editable in the UI.


⚠️ Limitation: Array → Object → Array → Object

4-level or deeper nested structures (Array → Object → Array → Object) are currently not supported for direct UI editing.

❌ Unsupported Example
{
"type": "object",
"properties": {
"departments": {
"type": "array",
"title": "Department List",
"items": {
"type": "object",
"properties": {
"departmentName": {"type": "string", "title": "Department Name"},
"employees": {
"type": "array",
"title": "Employee List",
"items": {
"type": "object",
"properties": {
"employeeName": {"type": "string", "title": "Employee Name"},
"skills": {
"type": "array",
"title": "Skills List",
"items": {
"type": "object",
"properties": {
"skillName": {"type": "string"}
}
}
}
}
}
}
}
}
}
}
}

Issue: 4-level structures like departments (Array) → employees (Object → Array) → skills (Object → Array) create nested repeating UIs within repeating UIs, which are currently not supported.


When deep nesting is necessary, split into multiple extended fields to handle it.

Solution Example: Split into 2 Extended Fields
Extended Field 1: departments_data (Department and Employee Information)
{
"type": "object",
"properties": {
"departmentId": {
"type": "string",
"title": "Department ID",
"description": "Unique department identifier"
},
"departmentName": {
"type": "string",
"title": "Department Name"
},
"employees": {
"type": "array",
"title": "Employee List",
"items": {
"type": "object",
"properties": {
"employeeId": {
"type": "string",
"title": "Employee ID"
},
"employeeName": {
"type": "string",
"title": "Employee Name"
},
"position": {
"type": "string",
"title": "Position",
"enum": ["manager","staff","intern"],
"enumNames": ["Manager","Staff","Intern"
]
}
}
}
}
}
}
Extended Field 2: employee_skills_data (Employee Skills Information)
{
"type": "object",
"properties": {
"employeeId": {
"type": "string",
"title": "Employee ID",
"description": "Corresponds to employee ID in departments_data"
},
"employeeName": {
"type": "string",
"title": "Employee Name (Reference)"
},
"employeeSkills": {
"type": "array",
"title": "Employee Skills List",
"items": {
"type": "object",
"properties": {
"skillName": {
"type": "string",
"title": "Skill Name"
},
"level": {
"type": "string",
"title": "Proficiency Level",
"enum": ["beginner","intermediate","advanced","expert"],
"enumNames": ["Beginner","Intermediate","Advanced","Expert"]
},
"yearsOfExperience": {
"type": "integer",
"title": "Years of Experience",
"minimum": 0
}
}
}
}
}
}

Benefits:

  • ✅ Each extended field stays within 3 levels (Object → Array → Object)
  • ✅ Fully editable in UI
  • ✅ Data linked using employeeId as key
  • ✅ Each data set can be managed independently

Data Linking:

  • Manage employee basic information in departments_data
  • Manage employee skills information in employee_skills_data
  • Link both using employeeId

📊 Nested Structure Support Table

Structure PatternLevelsUI SupportExample
Object1 level{type: "object"}
Array → Object2 levelsNews list, Product variations
Object → Array → Object3 levelsUser info → Order history
Array → Object → Array → Object4 levelsDepartments → Employees → Skills
Deeper nesting5+ levels-

📝 Summary

  • Up to Object: ✅ Supported
  • Up to Array → Object: ✅ Supported
  • Up to Object → Array → Object: ✅ Supported
  • Array → Object → Array → Object and beyond: ❌ Not supported

How to handle when 4+ levels are needed:

  1. Review data structure and split into multiple extended fields
  2. Link data with ID fields
  3. Keep each extended field within 3 levels (Object → Array → Object)

This design pattern allows managing complex data structures while maintaining a fully editable state in the UI.


Support

If you have any other questions, please contact us or check out Our Slack Community.