Skip to main content

Writing a TransformScript

Every TransformScript has the same two-part structure: a header of directives, followed by a body that is a single expression producing the result. The two parts are separated by a --- line. Understanding this structure tells you where to declare your inputs, outputs, and reusable values, and where the actual transformation logic goes.

%files 1.0
input json
output json
var greeting = "Hello, "
---
{ message: greeting ++ payload.name }

The --- separator divides the header from the body. A script with no --- is invalid. The split happens at the first ---, so a literal --- placed inside the header ends the header early.

The Header

The header is a sequence of directives, one per line. It supports // and # line comments and /* … */ block comments. Every directive is optional. A bare --- <expr> is a valid script.

DirectiveFormPurpose
Version%files 1.0 (or %fts 1.0)Declares the dialect and version. %dw 2.0 is accepted for DataWeave compatibility. The version is pinned exactly: %files must be 1.0 and %dw must be 2.0. Anything else is an error.
inputinput <format> [prop=value, …]Declares how payload is deserialized. Defining it twice is an error.
outputoutput <format> [prop=value, …]Declares how the result is serialized. Defining it twice is an error.
varvar name = <expr>A named binding, evaluated once and available in the body.
funfun name(params) = <expr>A named function available in the body.
nsns <prefix> <uri>Declares an XML namespace prefix for use in selectors and output.
importimport …Accepted and ignored. TransformScript is single-script and has no imports. See Differences from DataWeave.

Any other directive is an error. The input and output directives take an optional comma-separated list of prop=value properties. Values may be quoted, with \n, \t, and \uXXXX escapes, or unquoted. Unquoted true, false, null, and numbers are coerced to their types.

The Inputs

A running script has access to a small set of root variables built for Automations:

  • payload is the file's contents. When the payload is supplied as raw bytes or a string, it is deserialized using the format from the input directive if one is declared, or the format auto-detected from the file's extension (.csv becomes CSV, .json becomes JSON, and so on). See Input and Output Formats. An already-parsed value passes through unchanged. Its shape depends on the format: a JSON object, an array of CSV rows, an EDI segment structure, and so on.
  • attributes is metadata about the Automation Run, supplied by the platform when the script runs inside an Automation.
  • vars holds values from earlier Automation steps. Header var bindings are also available as ordinary variables in the body.

Referencing a name that isn't bound evaluates to null rather than raising an error. A script that reads attributes outside of an Automation simply sees null.

The Body

The body is a single expression. There are no statement lists. You introduce intermediate values with header var and fun, with the using(…) binding form, or with a do { … --- … } block. The expression is typically an object or array literal that assembles the output, but it can be any expression: a function chain, a match, a conditional, or a scalar.

Size Limits

Files are read fully into memory. TransformScript does not stream. Input is limited to 100 MB and output to 200 MB.

Output Formats

The output directive selects how the result is serialized:

output valueSerializes to
jsonJSON
ndjsonnewline-delimited JSON
csvCSV
xlsxExcel spreadsheet
xmlXML
yamlYAML
urlencodedapplication/x-www-form-urlencoded
hl7HL7 v2
edifactEDIFACT
x12X12

MIME types are accepted in place of the short names, for example application/json. An unknown format raises an error. With no output directive, the script yields the raw value with no serialized form. The same set of formats backs the input directive. See Input and Output Formats.

Examples

JSON in, JSON out, with a header var:

%files 1.0
input json
output json
var greeting = "Hello, "
---
{ message: greeting ++ payload.name, count: sizeOf(payload.items) }

{"name":"Alice","items":[1,2,3]}{"message":"Hello, Alice","count":3}

CSV in, where the payload becomes an array of row objects, and JSON out:

%files 1.0
input csv
output json
---
payload map (row) -> { name: row.name, upper_name: upper(row.name) }

name,age / bob,30 / cara,40[{"name":"bob","upper_name":"BOB"},{"name":"cara","upper_name":"CARA"}]

A header fun, with no payload:

%files 1.0
output json
fun double(x) = x * 2
---
double(21)

42