Schema Development Guide
For: Developers designing JSON schemas
Level: Intermediate
Time to read: 25 minutes
Examples: 12+ complete schemas
This guide shows how to design, evolve, and test JSON schemas used in Cascade workflows for forms, validation, and UI rendering.
JSON Schema Fundamentals
Minimal Schema
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"title": "Contact",
"properties": {
"name": {
"type": "string",
"title": "Full Name"
},
"email": {
"type": "string",
"title": "Email",
"format": "email"
}
},
"required": ["name", "email"],
"additionalProperties": false
}Schema Structure
$schema - JSON Schema version (always draft-07)
type - Data type (object, string, number, etc)
title - Human-readable name
properties - Object field definitions
required - Mandatory fields
additionalProperties - Allow/disallow extra fieldsSchema Design Patterns
Pattern 1: Text & Number Inputs
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"full_name": {
"type": "string",
"title": "Full Name",
"minLength": 1,
"maxLength": 100
},
"age": {
"type": "integer",
"title": "Age",
"minimum": 0,
"maximum": 150
},
"salary": {
"type": "number",
"title": "Annual Salary",
"minimum": 0,
"multipleOf": 100 // Must be multiple of 100
},
"bio": {
"type": "string",
"title": "Biography",
"minLength": 10,
"maxLength": 1000,
"x-ui-type": "textarea",
"x-ui-rows": 5
}
}
}Pattern 2: Enums & Dropdowns
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"department": {
"type": "string",
"title": "Department",
"enum": ["engineering", "sales", "marketing", "hr"],
"default": "engineering"
},
"access_level": {
"type": "string",
"title": "Access Level",
"enum": ["viewer", "editor", "admin"],
"x-ui-type": "select"
},
"languages": {
"type": "array",
"items": {
"type": "string",
"enum": ["english", "spanish", "french", "german"]
},
"title": "Languages",
"x-ui-type": "multi-select"
}
}
}Pattern 3: Nested Objects
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"applicant": {
"type": "object",
"title": "Applicant Information",
"properties": {
"first_name": {"type": "string"},
"last_name": {"type": "string"},
"date_of_birth": {"type": "string", "format": "date"}
},
"required": ["first_name", "last_name"]
},
"address": {
"type": "object",
"title": "Address",
"properties": {
"street": {"type": "string"},
"city": {"type": "string"},
"state": {"type": "string"},
"zip": {"type": "string", "pattern": "^[0-9]{5}$"}
},
"required": ["street", "city", "state", "zip"]
}
}
}Pattern 4: Arrays & Collections
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"items": {
"type": "array",
"title": "Order Items",
"items": {
"type": "object",
"properties": {
"sku": {"type": "string"},
"quantity": {"type": "integer", "minimum": 1},
"price": {"type": "number"}
},
"required": ["sku", "quantity", "price"]
},
"minItems": 1,
"maxItems": 100
},
"tags": {
"type": "array",
"items": {"type": "string"},
"title": "Tags",
"x-ui-type": "tag-input"
}
}
}Pattern 5: Conditional Fields
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"employment_type": {
"type": "string",
"title": "Employment Type",
"enum": ["w2", "contractor", "freelance"]
},
"ssn": {
"type": "string",
"title": "SSN (W2 only)",
"pattern": "^[0-9]{3}-[0-9]{2}-[0-9]{4}$",
"x-ui-visible-if": "{{ form.employment_type === 'w2' }}"
},
"tax_id": {
"type": "string",
"title": "Tax ID",
"x-ui-visible-if": "{{ form.employment_type === 'contractor' }}"
}
},
"required": ["employment_type"]
}Real-World Example: Loan Application Evolution
V1.0 - Initial Schema (Simple)
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Loan Application",
"type": "object",
"properties": {
"applicant_name": {"type": "string"},
"email": {"type": "string", "format": "email"},
"phone": {"type": "string"},
"annual_income": {"type": "number"},
"amount_requested": {"type": "number"}
},
"required": ["applicant_name", "email", "annual_income", "amount_requested"]
}V2.0 - Enhanced Schema (Backward Compatible)
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Loan Application",
"type": "object",
"properties": {
"applicant_name": {"type": "string"},
"email": {"type": "string", "format": "email"},
"phone": {"type": "string"},
"annual_income": {"type": "number"},
"amount_requested": {"type": "number"},
// NEW: Additional fields
"credit_score": {
"type": "integer",
"title": "Credit Score (optional)"
},
"employment_status": {
"type": "string",
"enum": ["employed", "self_employed", "retired"]
},
"existing_debts": {
"type": "number",
"title": "Existing Monthly Debts"
}
},
"required": ["applicant_name", "email", "annual_income", "amount_requested"]
// V1 fields still required, new fields optional
}V3.0 - Structured Schema (Backward Compatible)
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Loan Application",
"type": "object",
"properties": {
"applicant": {
"type": "object",
"title": "Applicant Information",
"properties": {
"name": {"type": "string"},
"email": {"type": "string", "format": "email"},
"phone": {"type": "string"},
"date_of_birth": {"type": "string", "format": "date"}
},
"required": ["name", "email"]
},
"financial": {
"type": "object",
"title": "Financial Information",
"properties": {
"annual_income": {"type": "number"},
"existing_debts": {"type": "number"},
"credit_score": {"type": "integer"}
},
"required": ["annual_income"]
},
"loan": {
"type": "object",
"title": "Loan Details",
"properties": {
"amount_requested": {"type": "number"},
"purpose": {
"type": "string",
"enum": ["home", "auto", "personal", "business"]
},
"term_months": {"type": "integer"}
},
"required": ["amount_requested"]
}
},
"required": ["applicant", "financial", "loan"]
}Schema Versioning Strategy
Version Numbering
MAJOR.MINOR.PATCH
MAJOR - Breaking changes (v1→v2)
MINOR - Backward-compatible additions
PATCH - Bug fixes, no behavioral changesBreaking Changes Examples
❌ Breaking:
- Removing a field (old apps send it, new schema rejects)
- Changing field type (string → number)
- Making optional field required
- Renaming fields
✅ Backward Compatible:
- Adding optional fields
- Adding enum values
- Loosening constraints (minLength 5→2)
- Grouping fields into new objects (if old fields still exist)
Evolution Pattern
# Schema versioning in URN
urn:cascade:schema:loan_application # Always latest (v3)
urn:cascade:schema:loan_application:v1 # Pinned version
urn:cascade:schema:loan_application:v2 # Pinned version
urn:cascade:schema:loan_application:v3 # Pinned version
# Workflow migration
# Old workflows: use v1
# New workflows: use v3
# Both work simultaneouslySchema Composition with $ref
Reusable Components
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"address": {
"type": "object",
"properties": {
"street": {"type": "string"},
"city": {"type": "string"},
"state": {"type": "string"},
"zip": {"type": "string"}
},
"required": ["street", "city"]
},
"contact": {
"type": "object",
"properties": {
"email": {"type": "string", "format": "email"},
"phone": {"type": "string"}
}
}
},
"type": "object",
"properties": {
"billing_address": {"$ref": "#/definitions/address"},
"shipping_address": {"$ref": "#/definitions/address"},
"contact_info": {"$ref": "#/definitions/contact"}
}
}Best Practices
✅ DO:
- Use semantic property names
- Add descriptions for complex fields
- Set reasonable min/max constraints
- Use
additionalProperties: falsefor strict validation - Test schema changes thoroughly
- Document breaking changes
- Version schemas consistently
- Use references to avoid duplication
❌ DON’T:
- Mix types (number AND string)
- Create deeply nested structures (
>3 levels) - Change field types between versions
- Remove required fields
- Make assumptions about data size
- Forget about backward compatibility
Testing Schemas
Validate Schema Structure
cascade schema validate urn:cascade:schema:loan_application
# Checks: JSON syntax, required properties, type consistencyTest with Sample Data
cascade schema test urn:cascade:schema:loan_application \
--input '{"applicant":{"name":"Alice","email":"alice@example.com"},...}'
# Validates data against schemaNext Steps
Need to build workflows? → Workflow Development Guide
Need activity help? → Activity Development Guide
Want to understand UI rendering? → Capabilities: UI Rendering
Updated: October 29, 2025
Version: 1.0
Examples: 12+ schemas
Patterns: 5 proven designs
Last updated on