Skip to content
Talk to our solutions team

Transforms

A transform normalises a value as it passes through. Declare them on a field, a type or a trait, and they run in the order written.

fields:
- name: email
type: string
transforms:
- type: trim
- type: lowercase

Every transform takes an optional params map. A transform that cannot handle the value it is given returns it unchanged rather than failing — a numeric transform on a string leaves the string alone. That keeps one bad row from failing a whole write, and it means a transform that silently does nothing is usually a type mismatch.

TransformParamsEffect
trimRemoves leading and trailing whitespace
ltrimLeading only
rtrimTrailing only
strip_whitespaceRemoves all whitespace, not just the ends
collapse_whitespaceRuns of whitespace become a single space
TransformParamsEffect
lowercasehello world
uppercaseHELLO WORLD
capitalizeFirst character upper, rest untouched
titleFirst Character Of Each Word
sentencecaseFirst character of the sentence only
camelcasehelloWorld
snakecasehello_world
kebabcasehello-world
slugURL-safe: lowercased, non-alphanumerics to hyphens
TransformParamsEffect
prefixvaluePrepends
suffixvalueAppends
replacefind, replaceReplaces every occurrence
regex_replaceexpression, replaceRegular-expression replace. An uncompilable pattern leaves the value unchanged
truncatelength, ellipsisCuts to length; ellipsis: true appends
pad_leftlength, charPads to length
pad_rightlength, charPads to length
strip_htmlRemoves tags, keeps text
mask_partialstart, end, charKeeps start leading and end trailing characters, masks the middle

mask_partial is the one to reach for on a stored identifier you still need to recognise — 4111********1111. For hiding a value from a reader rather than changing it, use the mask compliance instead: a transform rewrites what is stored, a compliance governs who sees it.

TransformParamsEffect
emptyasnullAn empty string becomes null
nullasemptyNull becomes an empty string
nullasdefaultvalueNull becomes value

Useful when a source system disagrees with your schema about which of empty and null means “absent”.

TransformParamsEffect
tostringTo text
tointegerTo a whole number; trims first
todoubleTo a float; trims first
tobooleanCase-insensitive; trims first
todateformatParses to a date; defaults to RFC 3339
TransformParamsEffect
roundprecisionNearest, to precision decimal places
ceilprecisionUpward
floorprecisionDownward
absAbsolute value
clampmin, maxConstrains to the range. Either bound may be omitted
format_numberformatFormats for display
TransformParamsEffect
format_dateformatReformats; RFC 3339 in, format out
TransformParamsEffect
base64_encode / base64_decodeBase64
url_encode / url_decodeQuery-string escaping
html_encode / html_decodeHTML entity escaping
hex_encode / hex_decodeHexadecimal
TransformParamsEffect
hashalgorithmNamed algorithm
hash_md5, md5MD5
hash_sha1SHA-1
hash_sha256SHA-256
hash_sha512, sha512SHA-512
hmacalgorithm, keyKeyed hash
TransformParamsEffect
uuid_v4Generates a random UUID
ulid_generateGenerates a ULID — time-ordered, so it sorts by creation
TransformParamsEffect
json_stringifyValue to JSON text
json_parseJSON text to a value
json_extractpathPulls one path out of a JSON value
TransformParamsEffect
splitseparatorText to a list
joinseparatorList to text
distinctRemoves duplicates
sortdirectionSorts; case-insensitive for text
flattendepthFlattens nested lists to depth
TransformParamsEffect
customexpression, languageRuns a script against the value

Use this when nothing above fits. Anything you would write more than twice belongs in a shared type or trait rather than repeated inline — see Types and Traits.

Transforms run top to bottom, and the wrong order is a real bug rather than a style question:

transforms:
- type: trim # " Hello World " → "Hello World"
- type: lowercase # → "hello world"
- type: slug # → "hello-world"

Reverse the trim and the slug and the leading space becomes a leading hyphen.

LevelApplies toUse when
FieldThat fieldOne-off normalisation
TypeEvery field of that typeThe rule belongs to the concept, not the column
TraitEvery entity pulling the trait inThe rule travels with a field set

Prefer the highest level that is still true. A lowercase on an email type is applied everywhere an email exists; the same transform copied onto nine fields is eight chances to forget the tenth.

  • Fields — declaring fields and their options
  • Types — reusable field types
  • Field protection — compliances, which govern access rather than content
  • Validations — rejecting a value rather than changing it