JSON Schema Basics
TinySystems uses JSON Schema to define port data structures. The SDK generates schemas automatically from Go structs, but understanding the underlying schema format helps when building complex components.
What is JSON Schema?
JSON Schema is a vocabulary for annotating and validating JSON documents. In TinySystems, schemas serve multiple purposes:
- UI Generation: The visual editor renders forms based on schemas
- Validation: Incoming data is validated against schemas
- Documentation: Schemas describe expected data formats
- Type Safety: Ensures data flows correctly between components
Schema Structure
A typical JSON Schema:
{
"type": "object",
"title": "HTTP Request",
"description": "An HTTP request configuration",
"properties": {
"method": {
"type": "string",
"title": "HTTP Method",
"enum": ["GET", "POST", "PUT", "DELETE"],
"default": "GET"
},
"url": {
"type": "string",
"title": "URL",
"format": "uri"
},
"body": {
"title": "Request Body"
}
},
"required": ["url"]
}
Basic Types
String
{
"type": "string",
"title": "Name",
"description": "Enter your name",
"minLength": 1,
"maxLength": 100,
"default": ""
}
Go equivalent:
Name string `json:"name" title:"Name" description:"Enter your name" minLength:"1" maxLength:"100"`
Number
{
"type": "number",
"title": "Amount",
"minimum": 0,
"maximum": 1000,
"default": 100
}
Go equivalent:
Amount float64 `json:"amount" title:"Amount" minimum:"0" maximum:"1000" default:"100"`
Integer
{
"type": "integer",
"title": "Count",
"minimum": 1,
"maximum": 100
}
Go equivalent:
Count int `json:"count" title:"Count" minimum:"1" maximum:"100"`
Boolean
{
"type": "boolean",
"title": "Enabled",
"default": true
}
Go equivalent:
Enabled bool `json:"enabled" title:"Enabled" default:"true"`
Array
{
"type": "array",
"title": "Items",
"items": {
"type": "string"
},
"minItems": 1,
"maxItems": 10
}
Go equivalent:
Items []string `json:"items" title:"Items" minItems:"1" maxItems:"10"`
Object
{
"type": "object",
"title": "Configuration",
"properties": {
"host": {"type": "string"},
"port": {"type": "integer"}
}
}
Go equivalent:
type Config struct {
Host string `json:"host"`
Port int `json:"port"`
}
Schema Keywords
Validation Keywords
| Keyword | Type | Description |
|---|---|---|
type | All | Data type (string, number, integer, boolean, array, object) |
enum | All | List of allowed values |
const | All | Single allowed value |
default | All | Default value |
String Keywords
| Keyword | Description |
|---|---|
minLength | Minimum string length |
maxLength | Maximum string length |
pattern | Regex pattern |
format | Semantic validation (email, uri, etc.) |
Number Keywords
| Keyword | Description |
|---|---|
minimum | Minimum value (inclusive) |
maximum | Maximum value (inclusive) |
exclusiveMinimum | Minimum value (exclusive) |
exclusiveMaximum | Maximum value (exclusive) |
multipleOf | Value must be multiple of |
Array Keywords
| Keyword | Description |
|---|---|
items | Schema for array items |
minItems | Minimum array length |
maxItems | Maximum array length |
uniqueItems | All items must be unique |
Object Keywords
| Keyword | Description |
|---|---|
properties | Property schemas |
required | List of required properties |
additionalProperties | Schema for extra properties |
Format Strings
The format keyword provides semantic validation:
| Format | Description | Example |
|---|---|---|
email | Email address | user@example.com |
uri | Full URI | https://example.com |
uri-reference | URI or relative reference | /path/to/resource |
date | ISO 8601 date | 2024-01-15 |
date-time | ISO 8601 datetime | 2024-01-15T10:30:00Z |
time | ISO 8601 time | 10:30:00 |
duration | ISO 8601 duration | P1D (1 day) |
ipv4 | IPv4 address | 192.168.1.1 |
ipv6 | IPv6 address | ::1 |
uuid | UUID | 550e8400-e29b-41d4-a716-446655440000 |
password | Masked input (UI hint) | ***** |
button | Button in UI | N/A |
Enum Values
Define allowed values:
{
"type": "string",
"title": "Log Level",
"enum": ["debug", "info", "warn", "error"],
"default": "info"
}
With display titles:
Level string `json:"level" title:"Log Level" enum:"debug,info,warn,error" enumTitles:"Debug,Info,Warning,Error"`
Required Fields
Mark fields as required:
{
"type": "object",
"properties": {
"name": {"type": "string"},
"email": {"type": "string"}
},
"required": ["name", "email"]
}
Go equivalent:
Name string `json:"name" required:"true"`
Email string `json:"email" required:"true"`
Nested Objects
{
"type": "object",
"properties": {
"server": {
"type": "object",
"title": "Server Settings",
"properties": {
"host": {"type": "string"},
"port": {"type": "integer"}
}
},
"auth": {
"type": "object",
"title": "Authentication",
"properties": {
"username": {"type": "string"},
"password": {"type": "string", "format": "password"}
}
}
}
}
Go equivalent:
type Settings struct {
Server ServerConfig `json:"server" title:"Server Settings"`
Auth AuthConfig `json:"auth" title:"Authentication"`
}
type ServerConfig struct {
Host string `json:"host"`
Port int `json:"port"`
}
type AuthConfig struct {
Username string `json:"username"`
Password string `json:"password" format:"password"`
}
Arrays of Objects
{
"type": "array",
"title": "Endpoints",
"items": {
"type": "object",
"properties": {
"name": {"type": "string"},
"url": {"type": "string", "format": "uri"}
},
"required": ["name", "url"]
}
}
Go equivalent:
type Settings struct {
Endpoints []Endpoint `json:"endpoints" title:"Endpoints"`
}
type Endpoint struct {
Name string `json:"name" required:"true"`
URL string `json:"url" format:"uri" required:"true"`
}
Any Type
For flexible data:
{
"title": "Data",
"description": "Any JSON value"
}
Go equivalent:
Data any `json:"data" title:"Data" description:"Any JSON value"`
Custom Keywords (UI Hints)
Beyond standard JSON Schema keywords, the SDK carries a fixed set of custom struct tags into the generated schema. These are the only custom tags the reflector recognizes (see pkg/schema/json.go):
| Tag | Description |
|---|---|
format | Rendering/validation hint: password, textarea, code, button, plus the standard formats above |
language | Editor language for format:"code" fields (e.g. json, javascript) |
readonly | Render the field read-only |
tab | Group the field under a named tab in the form |
colSpan | Grid width of the field (e.g. col-span-6) |
align | Alignment hint |
requiredWhen / optionalWhen | Conditional required-ness, evaluated by the form renderer |
configurable | Marks the definition editable per edge — see Configurable Overlay |
shared | Marks the definition shared across the flow |
$ref / type | Override the reference / JSON type of the generated property |
enumTitles | Comma-separated display labels for enum values |
propertyOrder | Display order — set automatically from struct declaration order on reflected schemas; set it manually only in hand-written schemas (Port.Schema) |
There is no widget or hidden tag. Multiline and code inputs are selected with format:
type Settings struct {
Name string `json:"name" title:"Name"`
Code string `json:"code" title:"Code" format:"code" language:"json"`
Details string `json:"details" title:"Details" format:"textarea" tab:"Advanced"`
}
Field order in the rendered form follows struct declaration order; the reflector stamps propertyOrder on every property for you.
Next Steps
- Schema from Go - Auto-generate schemas
- Secrets in Settings - Reference secrets
- Dynamic Schemas - Runtime schemas