Schema Definition

TON provides built-in schema validation with path-based property specifications.

Path-Based Schema Syntax

TON uses forward slashes to specify property paths in schemas:

{(user)
    name = "John",
    email = "[email protected]",

    details = {
        bio = "Software engineer",
        avatar = "avatar.jpg"
    }
}

#! {(user)
    /name = string(required, maxLength(100)),
    /email = string(required, format(email)),
    /details/bio = string(maxLength(1000)),
    /details/avatar = string(maxLength(255))
}

Why Path-Based Syntax?

  • Clear Hierarchy: Paths mirror the data structure
  • Unambiguous: Each property has a unique path
  • Familiar: Similar to file paths and URLs
  • Deep Validation: Apply rules to nested properties

Schema Placement

// Schema at end of file
{(data)
    // ... data ...
}

#! {(data)
    // ... schema rules ...
}

// Or reference external schema
#@ @schemaFile = 'schema.ton'

Validation Rules

Universal Rules (All Types)

  • required - Property must be present
  • notnull - Cannot be null
  • default(value) - Default for missing
  • defaultWhenNull(value) - Default for null
  • defaultWhenEmpty(value) - Default for empty
  • defaultWhenInvalid(value) - Default on validation failure

String Validation

/name = string(minLength(1), maxLength(100))
/email = string(format(email))
/url = string(pattern("^https?://"))
/bio = string(multiline(true), maxLength(1000))

Number Validation

/age = int(min(0), max(150))
/score = float(range(0.0, 100.0))
/port = int(range(1, 65535))
/flags = int(bits(8), unsigned)

Array Validation

/tags = array:string(minCount(1), maxCount(10))
/scores = array:float(unique, sorted)
/matrix = array:array:int(maxCount(10))

Complex Example

{(company)
    name = "TechCorp",
    employees = 250,

    headquarters = {
        address = "123 Tech St",
        city = "San Francisco",

        coordinates = {
            latitude = 37.7749,
            longitude = -122.4194
        }
    },

    2024revenue = 1500000,
    departments = [
        {(dept) name = "Engineering", count = 120},
        {(dept) name = "Sales", count = 80}
    ]
}

#! {(company)
    /name = string(required, maxLength(100)),
    /employees = int(min(1), max(10000)),

    # Nested paths
    /headquarters/address = string(required),
    /headquarters/city = string(required),

    # Deep nested paths
    /headquarters/coordinates/latitude = float(range(-90.0, 90.0)),
    /headquarters/coordinates/longitude = float(range(-180.0, 180.0)),

    # Numeric property paths
    /2024revenue = float(positive),

    # Array validation
    /departments = array:object(minCount(1))
}

#! {(dept)
    /name = string(required),
    /count = int(positive)
}

Enum Definitions

#! enum(status) [pending, active, completed, cancelled]
#! enumSet(permissions) [read, write, delete, admin]

#! {(user)
    /status = enum:status(required),
    /permissions = enumSet:permissions(minCount(1))
}