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
trim—Removes leading and trailing whitespace
ltrim—Leading only
rtrim—Trailing only
strip_whitespace—Removes all whitespace, not just the ends
collapse_whitespace—Runs of whitespace become a single space
TransformParamsEffect
lowercase—hello world
uppercase—HELLO WORLD
capitalize—First character upper, rest untouched
title—First Character Of Each Word
sentencecase—First character of the sentence only
camelcase—helloWorld
snakecase—hello_world
kebabcase—hello-world
slug—URL-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_html—Removes 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
emptyasnull—An empty string becomes null
nullasempty—Null 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
tostring—To text
tointeger—To a whole number; trims first
todouble—To a float; trims first
toboolean—Case-insensitive; trims first
todateformatParses to a date; defaults to RFC 3339
TransformParamsEffect
roundprecisionNearest, to precision decimal places
ceilprecisionUpward
floorprecisionDownward
abs—Absolute 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_decode—Base64
url_encode / url_decode—Query-string escaping
html_encode / html_decode—HTML entity escaping
hex_encode / hex_decode—Hexadecimal
TransformParamsEffect
hashalgorithmNamed algorithm
hash_md5, md5—MD5
hash_sha1—SHA-1
hash_sha256—SHA-256
hash_sha512, sha512—SHA-512
hmacalgorithm, keyKeyed hash
TransformParamsEffect
uuid_v4—Generates a random UUID
ulid_generate—Generates a ULID: time-ordered, so it sorts by creation
TransformParamsEffect
json_stringify—Value to JSON text
json_parse—JSON text to a value
json_extractpathPulls one path out of a JSON value
TransformParamsEffect
splitseparatorText to a list
joinseparatorList to text
distinct—Removes 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