Extend table JSON with validated custom fields that become first-class metadata.
Custom properties are user-defined key-value pairs that you add directly to table definition
JSON files. Any key that is not a recognized standard property is treated as a custom property.
They serve two purposes: carrying metadata your team defines (data classification, ownership,
environment tags) and acting as runtime
script tokens that drive conditional logic in expression
fields like ShouldApplyExpression and Default.
Custom properties enable use cases like:
Properties can be simple values, nested objects (flattened via dot-notation for tokens), or arrays (comma-joined for tokens). They can be grouped into sub-objects for logical organization and optional-group JSON schema validation.
Custom properties can appear at the table level or inside any component array entry. Properties set at one level are independent of those at any other level. There is no inheritance from table to column.
| Component | Appears In |
|---|---|
| Table | Top-level table definition file |
| Column | Columns array |
| Index | Indexes array |
| ForeignKey | ForeignKeys array |
| CheckConstraint | CheckConstraints array |
| Statistic | Statistics array |
| ExcludeConstraint | ExcludeConstraints array |
A column with custom properties alongside standard ones:
{
"Name": "amount",
"DataType": "numeric(18,2)",
"Nullable": false,
"DataClassification": "Financial",
"MaskInNonProd": "true"
}
Custom properties become {{TokenName}} substitutions in expression fields.
Token matching is case-insensitive. Tokens with no matching property are left unchanged.
ShouldApplyExpression
using bare names (e.g., {{Environment}}), and in all component expressions
using a Table. prefix (e.g., {{Table.Environment}})| Component | Token-Substituted Fields |
|---|---|
| Table | ShouldApplyExpression |
| Column | ShouldApplyExpression, Default, GenerationExpression |
| Index | ShouldApplyExpression, FilterExpression |
| ForeignKey | ShouldApplyExpression |
| CheckConstraint | ShouldApplyExpression, Expression |
| ExcludeConstraint | ShouldApplyExpression, FilterExpression |
| Statistic | ShouldApplyExpression |
Object values are flattened using dot notation:
{
"Retention": {
"Policy": "7years",
"Tier": "Hot"
}
}
Produces tokens {{Retention.Policy}} and {{Retention.Tier}}.
From a component expression, use {{Table.Retention.Policy}}.
Array values are joined with commas:
{
"ResponsibleTeams": [
"Billing",
"Compliance"
]
}
Produces token {{ResponsibleTeams}} with value Billing,Compliance.
A table-level custom property controlling whether an index is applied:
{
"Schema": "public",
"Name": "orders",
"Environment": "production",
"Indexes": [
{
"Name": "ix_orders_created_date",
"Columns": "created_date",
"ShouldApplyExpression": "SELECT CASE WHEN '{{Table.Environment}}' = 'production' THEN 1 ELSE 0 END"
}
]
}
Custom properties appear in the SchemaHammer UI when defined
in the tables.schema file located in the .json-schemas folder of
your product repository. This file drives both JSON schema validation (for GitHub Actions or
other CI checks) and the custom editor controls in the UI.
| Type | UI Control | Modifiers |
|---|---|---|
int, number | Numeric input | minimum, maximum, multipleOf, exclusiveMinimum, exclusiveMaximum |
boolean | Checkbox | |
string | Text input | pattern, minLength, maxLength, format (date, time, date-time) |
enum | Fixed dropdown | meta:enum for code/description pairs |
string with pattern | Dropdown (if pattern is pipe-separated single values) | |
string desc: DROPDOWN:<file> | Dropdown from external JSON | |
string desc: SQL | SQL editor (with pop-out) | |
string desc: MEMO | Multi-line textbox | |
object desc: DICTIONARY | Key/value pair editor | |
array desc: CHECKLIST:<file> | Multi-select checklist from external JSON |
The custom editors perform validations for min, max, and pattern modifiers when saving to help users avoid issues in their PRs.
By default, the control label is derived by splitting the property name on camel case.
Set the title property in the schema file to override with a custom label.
When SchemaTongs re-extracts a table from a live database into a schema package that already
has a definition file for that table, all custom properties from the previous file are preserved.
Component matching uses the Name property (case-sensitive, quotes trimmed).
Columns and tables also fall back to OldName for renamed components.
| Component | Matched By |
|---|---|
| Table | (root object) |
| Column | Name, then OldName |
| Index | Name |
| ForeignKey | Name |
| CheckConstraint | Name |
| Statistic | Name |
| ExcludeConstraint | Name |