8.1 DataWeave 2.0 Syntax, Type System & Selectors

Key Takeaways

  • DataWeave 2.0 scripts comprise two distinct zones: the Header (defining %dw 2.0, output MIME types, custom types, variables, functions, and module imports) and the Body (a single functional expression returning the output payload), separated strictly by a three-dash delimiter (---).
  • DataWeave is a strongly typed, functional, expression-oriented language with immutable data structures, supporting primitive types (String, Number, Boolean, Null, Binary), temporal types (Date, DateTime, Time, TimeZone, Period), collection types (Array, Object, Range), and Union types (TypeA | TypeB).
  • Type coercion using the as operator allows converting between types with optional formatting properties (e.g., payload.date as Date {format: 'yyyy-MM-dd'}, payload.cost as Number as String {format: '$#,##0.00'}).
  • Selector syntax provides rich navigation over JSON, XML, Java, and CSV structures: Single-value (.), Multi-value (.*), Descendant (..), Key-value pair (.&), Index ([n], [-n]), Range ([n to m]), and Dynamic bracket selector ([dynamicKey]).
  • The safe navigation operator (?.) prevents null pointer runtime errors when traversing optional or missing intermediate object paths, and the default operator provides fallback values when expressions evaluate to null.
Last updated: August 2026

DataWeave 2.0 Syntax, Type System & Selectors

In Mule 4, DataWeave 2.0 serves as the primary language for data transformation, querying, and expression evaluation. Designed from the ground up for high-performance enterprise integration, DataWeave is a functional, strongly typed, and expression-oriented language. Unlike imperative programming languages where state is mutated sequentially, DataWeave treats data as immutable and evaluates scripts as pure mathematical expressions that transform input streams directly into output streams.


1. Anatomy of a DataWeave 2.0 Script

Every DataWeave 2.0 script is structured into two mandatory physical sections: the Header and the Body, separated by a three-hyphen delimiter (---).

+-----------------------------------------------------------------------------------------+
|                           DATAWEAVE 2.0 SCRIPT ANATOMY                                  |
|                                                                                         |
|   +---------------------------------------------------------------------------------+   |
|   | HEADER SECTION (Directives & Declarations)                                      |   |
|   |   %dw 2.0                                    --> Language Version               |   |
|   |   output application/json                    --> Output MIME Type & Directives  |   |
|   |   import * from dw::core::Strings            --> Standard / Custom Imports      |   |
|   |   var taxRate = 0.0825                       --> Global Constant / Variable     |   |
|   |   type Currency = "USD" | "EUR" | "GBP"       --> Custom / Union Type Definition |   |
|   |   fun formatName(first: String, last: String) = upper(last) ++ ", " ++ first    |   |
|   +---------------------------------------------------------------------------------+   |
|                                            |                                            |
|                                            v                                            |
|   ===================================  ---  =========================================   |
|                                            | (Three-Dash Delimiter)                     |
|                                            v                                            |
|   +---------------------------------------------------------------------------------+   |
|   | BODY SECTION (Single Functional Expression)                                     |   |
|   |   {                                                                             |   |
|   |       fullName: formatName(payload.firstName, payload.lastName),                |   |
|   |       totalWithTax: payload.subtotal * (1 + taxRate),                           |   |
|   |       items: payload.lineItems map ((item) -> { ... })                          |   |
|   |   }                                                                             |   |
|   +---------------------------------------------------------------------------------+   |
+-----------------------------------------------------------------------------------------+

Header Directives

  1. Language Version Directive (%dw 2.0): Must always appear as the very first line of a DataWeave 2.0 script.
  2. Output Directive (output <mimeType>): Specifies the serialization target format (e.g., output application/json, output application/xml, output application/csv, output application/java) along with optional writer properties (e.g., indent=false, header=true).
  3. Variable Declarations (var): Declares immutable global script-level constants. Once declared, variable values cannot be reassigned.
  4. Function Declarations (fun): Defines reusable custom transformation functions with optional argument types, default values, and return type declarations.
  5. Type Declarations (type): Defines custom types, object schemas, or union types.
  6. Module Imports (import): Imports built-in or custom DataWeave modules from standard libraries (dw::core::Strings, dw::core::Arrays, dw::util::Values, etc.).
  7. Namespace Declarations (ns): Declares XML namespaces for reading and writing qualified XML elements and attributes.

The Expression Body

The DataWeave body consists of exactly one expression that evaluates to the output data structure. There are no return statements, loop blocks, or variable mutations; the result of evaluating the root expression becomes the payload returned to the Mule flow.


2. The DataWeave 2.0 Type System

DataWeave 2.0 features a rich type system that guarantees type safety across complex data transformations.

+-----------------------------------------------------------------------------------------+
|                             DATAWEAVE TYPE HIERARCHY                                    |
|                                                                                         |
|   [Any] (Root Supertype)                                                                |
|     |-- [Simple / Primitive Types]                                                      |
|     |     |-- String ("Acme Corp", 'Order-123')                                         |
|     |     |-- Number (42, 3.14159, -0.05)                                               |
|     |     |-- Boolean (true, false)                                                     |
|     |     |-- Null (null)                                                               |
|     |     |-- Binary (raw byte streams, Base64 content)                                 |
|     |                                                                                   |
|     |-- [Temporal Types]                                                                |
|     |     |-- Date (|2026-08-22|)                                                       |
|     |     |-- DateTime (|2026-08-22T14:30:00Z|, |2026-08-22T14:30:00-07:00|)            |
|     |     |-- Time (|14:30:00|)                                                         |
|     |     |-- TimeZone (|-07:00|, |UTC|)                                                |
|     |     |-- Period (|P1Y2M3DT4H5M6S|)                                                 |
|     |                                                                                   |
|     |-- [Complex / Collection Types]                                                    |
|     |     |-- Array ([ 1, 2, 3, "A", "B" ])                                             |
|     |     |-- Object ({ key1: "value1", key2: 100 })                                    |
|     |     |-- Range (0 to 10, 'a' to 'z')                                               |
|     |     |-- Key (object field keys, e.g., name in { name: "John" })                   |
|     |                                                                                   |
|     +-- [Union Types]                                                                   |
|           +-- (TypeA | TypeB) (e.g., Number | String, "ACTIVE" | "INACTIVE")            |
+-----------------------------------------------------------------------------------------+

Primitive Types

  • String: Unicode character sequences enclosed in double quotes ("...") or single quotes ('...'). Multiline strings support triple quotes ("""...""").
  • Number: Numeric integers and floating-point decimal numbers without size limits.
  • Boolean: Logical values true or false.
  • Null: Represents the absence of a value (null).
  • Binary: Stream of raw binary bytes.

Temporal Types

Temporal literals in DataWeave are enclosed between pipe characters (|...|):

  • Date: |2026-08-22|
  • DateTime: |2026-08-22T14:30:00Z| (ISO-8601 UTC) or |2026-08-22T14:30:00-07:00|
  • Time: |14:30:00|
  • Period: Represents durations (e.g., |P1Y2M| or |PT15M|). Can be added to or subtracted from dates: |2026-08-22| + |P7D| yields |2026-08-29|.

Union Types & Custom Type Aliases

Union types allow a variable or property to accept one of multiple predefined types:

%dw 2.0
output application/json

type HttpMethod = "GET" | "POST" | "PUT" | "DELETE"
type NumericIdentifier = Number | String
type Address = {
    street: String,
    city: String,
    postalCode: String,
    country?: String // Optional field
}
---
{
    status: "OK"
}

3. Type Coercion & Formatting Properties

DataWeave uses the as operator for explicit type casting and conversion. Coercion can be parameterized with custom formatting options enclosed in curly braces {}.

+-----------------------------------------------------------------------------------------+
|                             TYPE COERCION MATRIX                                        |
|                                                                                         |
|   From Type  --->  To Type      Expression Syntax                                       |
|   ---------        -------      -----------------                                       |
|   String     --->  Number       "1250.75" as Number                                     |
|   Number     --->  String       1250.75 as String {format: "$#,##0.00"}  --> "$1,250.75"|
|   String     --->  Date         "2026-08-22" as Date {format: "yyyy-MM-dd"}             |
|   DateTime   --->  String       now() as String {format: "MM/dd/yyyy HH:mm:ss"}         |
|   String     --->  Boolean      "true" as Boolean                                       |
|   Number     --->  Boolean      (non-zero is not automatic; use value != 0)             |
|   Object     --->  Array        payload pluck ((v, k) -> { (k): v })                    |
+-----------------------------------------------------------------------------------------+

Formatting Examples

%dw 2.0
output application/json
var rawTimestamp = "2026-08-22T14:30:00Z"
var unitPrice = 1499.9
---
{
    // String to DateTime to Formatted String
    displayDate: (rawTimestamp as DateTime) as String {format: "dd MMM yyyy, hh:mm a"},
    
    // Number to Currency String
    formattedPrice: unitPrice as String {format: "$#,##0.00"},
    
    // String to Number arithmetic
    adjustedTotal: ("450.50" as Number) * 1.10,
    
    // String to Date
    invoiceDate: "22/08/2026" as Date {format: "dd/MM/yyyy"}
}

Output Result:

{
  "displayDate": "22 Aug 2026, 02:30 PM",
  "formattedPrice": "$1,499.90",
  "adjustedTotal": 495.55,
  "invoiceDate": "2026-08-22"
}

[!IMPORTANT] Two-Step Temporal Formatting An input string cannot be directly coerced to another string format with {format: ...}. You must first coerce the String to a temporal type (DateTime or Date), and then coerce that temporal type back to a String with the desired format mask: (payload.str as DateTime) as String {format: "yyyy/MM/dd"}.


4. Advanced Selector Syntax Cheat Sheet

Selectors allow extracting data from nested objects, arrays, XML trees, and Java maps. DataWeave provides seven primary selector types:

Selector TypeSyntaxReturn TypeDescription & Behavior
Single-Valuepayload.user.nameAny (Value)Returns the first matching child value. If no match is found, returns null.
Multi-Valuepayload.users.*nameArray<Any>Returns an array containing all matching child values for repeated keys.
Descendantpayload..nameArray<Any>Recursively traverses all nested hierarchies at any depth and returns an array of all matching values.
Key-Value Pairpayload.&nameObjectReturns an Object containing both the key and the value ({ name: "John" }) rather than the raw value alone.
Indexpayload[0], payload[-1]AnyReturns the item at index n (0-based). Negative index -1 retrieves the last element.
Rangepayload[0 to 2]ArraySlices a sub-array or substring from start index to end index (inclusive).
Dynamicpayload[vars.fieldName]AnyEvaluates a dynamic expression or variable inside brackets to select a matching object field.
+-----------------------------------------------------------------------------------------+
|                             SELECTOR RESOLUTION FLOW                                    |
|                                                                                         |
|   Given XML / JSON Payload:                                                             |
|   {                                                                                     |
|       "store": {                                                                        |
|           "book": [ { "title": "Mule 4 Guide", "price": 40 },                           |
|                     { "title": "DataWeave Handbook", "price": 50 } ],                   |
|           "manager": { "title": "Store Lead" }                                          |
|       }                                                                                 |
|   }                                                                                     |
|                                                                                         |
|   1. Single-Value: payload.store.book.title   ---> "Mule 4 Guide"                       |
|   2. Multi-Value:  payload.store.book.*title  ---> [ "Mule 4 Guide",                    |
|                                                      "DataWeave Handbook" ]             |
|   3. Descendant:   payload..title             ---> [ "Mule 4 Guide",                    |
|                                                      "DataWeave Handbook",              |
|                                                      "Store Lead" ]                     |
|   4. Index:        payload.store.book[-1]     ---> { "title": "DataWeave Handbook", ...}|
|   5. Range:        payload.store.book[0 to 1] ---> [ { ... }, { ... } ]                 |
+-----------------------------------------------------------------------------------------+

XML Multi-Value vs Single-Value Example

In XML processing, repeated elements (e.g., <item>) frequently occur within a parent element. Using the single-value selector payload.order.item returns only the first <item>, whereas the multi-value selector payload.order.*item returns an array of all <item> elements:

// Input XML:
// <order>
//   <item><id>101</id><name>Laptop</name></item>
//   <item><id>102</id><name>Monitor</name></item>
// </order>

%dw 2.0
output application/json
---
{
    firstItemName: payload.order.item.name,       // Result: "Laptop"
    allItems: payload.order.*item.name,          // Result: ["Laptop", "Monitor"]
    allIdsRecursive: payload..id                 // Result: ["101", "102"]
}

5. Null Safety Navigation & The Default Operator

Navigating deeply nested structures where intermediate objects or arrays may be null or undefined is a primary source of integration runtime faults.

Safe Navigation Operator (?.)

When accessing a nested field through standard dot notation (payload.order.customer.address.city), if customer is null, DataWeave will throw a NullPointerException (cannot navigate null value). The safe navigation operator (?.) suppresses errors and evaluates cleanly to null if any intermediate property is missing or null:

%dw 2.0
output application/json
---
{
    // Safe navigation across potentially absent nested hierarchy
    billingCity: payload.order?.customer?.billingAddress?.city
}

The Default Operator (default)

The default operator provides a fallback value when the left-hand expression evaluates to null.

%dw 2.0
output application/json
---
{
    customerStatus: payload.status default "STANDARD",
    creditLimit: payload.creditLimit as Number default 1000,
    shippingMethod: payload.delivery?.method default "GROUND"
}

Safe Navigation Chained with Default:

// Idiomatic defensive DataWeave pattern:
street: payload.customer?.address?.street default "N/A"

[!WARNING] default Only Evaluates on null The default operator triggers only when the expression evaluates to null. It does not trigger on empty strings (""), empty arrays ([]), empty objects ({}), or boolean false.

  • "" default "Fallback" evaluates to "" (empty string).
  • [] default ["Fallback"] evaluates to [] (empty array).
  • To handle empty strings, combine with isEmpty(): if (isEmpty(payload.name)) "Fallback" else payload.name.

6. Exam Watch: Core Syntax & Selector Scenarios

[!IMPORTANT] Multi-Value (.*) vs Descendant (..)

  • Multi-value selector (.*key) matches only direct children of the target element sharing the specified key name.
  • Descendant selector (..key) traverses the entire subtree recursively at all depths.

[!TIP] XML Namespace Declarations When querying XML documents with namespaces (e.g., <soap:Envelope xmlns:soap="...">), you must declare ns soap http://schemas.xmlsoap.org/soap/envelope/ in the header and qualify selectors as payload.soap#Envelope.soap#Body.

Test Your Knowledge

An inbound XML order payload contains multiple repeated <item> elements inside a parent <order> element: <order><item><name>Laptop</name></item><item><name>Dock</name></item><item><name>Mouse</name></item></order>. Which DataWeave selector expression returns an Array containing the names of all three items?

A
B
C
D
Test Your Knowledge

A Mule 4 application receives a JSON payload where customer.billingAddress is optional and may be null or completely absent. Which DataWeave expression safely extracts postalCode without throwing a runtime NullPointerException if billingAddress is null, while defaulting to "00000" when the postal code is absent?

A
B
C
D
Test Your Knowledge

A developer receives an ISO-8601 UTC timestamp string "2026-08-22T14:30:00Z" in payload.timestamp. The requirement is to output the date and time as a string formatted as "08/22/2026 02:30 PM". Which DataWeave expression correctly performs this conversion?

A
B
C
D
Test Your Knowledge

A complex JSON document has arbitrary and variable levels of nesting where "sku" keys may appear at the root level, inside line items, or within sub-assemblies. Which selector expression extracts all SKU values from across the entire payload into a single flat Array regardless of depth?

A
B
C
D