MuleSoft DataWeave Functions

DataWeave functions let you define reusable transformation logic by name and call it multiple times within a script. Instead of repeating the same logic in three places, you write it once as a function and call it wherever needed. Functions make DataWeave scripts shorter, cleaner, and easier to maintain.

Defining a Function

Define functions in the DataWeave header using the fun keyword. Give the function a descriptive name, list its parameters in parentheses, and write the transformation after the = sign.

Function Definition Syntax

%dw 2.0
output application/json
fun functionName(param1, param2) = expression using param1 and param2
---
body

Simple Function Example

%dw 2.0
output application/json
fun formatName(first, last) = last ++ ", " ++ first
---
{
  "customer1": formatName(payload.customers[0].first, payload.customers[0].last),
  "customer2": formatName(payload.customers[1].first, payload.customers[1].last)
}

// If payload.customers[0] = {first:"Alice", last:"Smith"}
// formatName("Alice", "Smith") returns "Smith, Alice"

Functions with Calculations

%dw 2.0
output application/json
fun calculateTotal(price, qty, taxRate) = 
  round((price * qty * (1 + taxRate)) * 100) / 100
---
{
  "lineItems": payload.lines map (line) -> {
    "product": line.name,
    "total":   calculateTotal(line.price, line.qty, 0.08)
  }
}

Functions with Conditions

%dw 2.0
output application/json
fun getShippingCost(weight, region) = 
  if (region == "domestic") 
    (if (weight > 5) 9.99 else 4.99)
  else 
    (if (weight > 5) 24.99 else 14.99)
---
payload map (order) -> {
  "orderId":      order.id,
  "shippingCost": getShippingCost(order.weightKg, order.region)
}

Built-in String Functions

DataWeave includes many built-in functions for string manipulation.

Common String Functions

upper("hello world")          // "HELLO WORLD"
lower("HELLO WORLD")          // "hello world"
trim("  hello  ")             // "hello"
replace("hello world")
  with "world" by "DataWeave" // "hello DataWeave"

splitBy("a,b,c", ",")         // ["a", "b", "c"]

startsWith("Hello", "He")     // true
endsWith("Hello", "lo")       // true
contains("Hello World", "World") // true

substringBefore("user@email.com", "@")  // "user"
substringAfter("user@email.com",  "@")  // "email.com"

sizeOf("MuleSoft")            // 8

Practical String Function Example

Input:
{ "rawPhone": "  (555) 123-4567  ", "email": "ALICE@EXAMPLE.COM" }

DataWeave:
%dw 2.0
output application/json
fun cleanPhone(phone) = 
  (phone 
    replace /[\s\(\)\-]/ with ""
    |> trim($))
---
{
  "phone": cleanPhone(payload.rawPhone),
  "email": lower(payload.email)
}

Output:
{ "phone": "5551234567", "email": "alice@example.com" }

Built-in Date and Time Functions

now()                           // Current datetime: 2024-01-15T09:30:00
today()                         // Current date: 2024-01-15
now() as Date                   // 2024-01-15
now() as String {format: "dd/MM/yyyy"}  // "15/01/2024"

// Parse a date string:
"2024-01-15" as Date {format: "yyyy-MM-dd"}

// Add days to a date:
now() + |P7D|                   // 7 days from now
now() - |P1M|                   // 1 month ago

// Compare dates:
("2024-01-15" as Date) > ("2024-01-01" as Date)  // true

Date Formatting Function

%dw 2.0
output application/json
fun formatDate(d, fmt) = d as String {format: fmt}
fun daysBetween(d1, d2) = 
  ((d2 as Date) - (d1 as Date)).days
---
{
  "orderDate":  formatDate(payload.createdAt as Date, "dd MMM yyyy"),
  "daysOld":    daysBetween(payload.createdAt, now() as Date {format: "yyyy-MM-dd"})
}

Built-in Math Functions

abs(-15)               // 15
ceil(4.2)              // 5
floor(4.8)             // 4
round(4.567)           // 5
round(4.567 * 100)/100 // 4.57  (round to 2 decimal places)
sqrt(16)               // 4.0
pow(2, 10)             // 1024.0
max([3, 1, 4, 1, 5])  // 5
min([3, 1, 4, 1, 5])  // 1
sum([1, 2, 3, 4, 5])  // 15
avg([10, 20, 30])      // 20.0

Type Conversion Functions

"42" as Number         // 42
42 as String           // "42"
"true" as Boolean      // true
"2024-01-15" as Date {format: "yyyy-MM-dd"}
3.14 as String {format: "#.##"}   // "3.14"

// Check type:
typeOf("hello")        // String
typeOf(42)             // Number
typeOf([1,2,3])        // Array
typeOf({a: 1})         // Object

Custom Reusable DataWeave Modules

For functions used across multiple flows in a project, create a dedicated DataWeave module file. Store it in src/main/resources/dwl/ and import it into any DataWeave script.

Creating a Module File

File: src/main/resources/dwl/CommonFunctions.dwl

%dw 2.0

fun maskCreditCard(cardNum) = 
  "****-****-****-" ++ substringAfter(cardNum, "-****-****-****-" takeLeft 0 as String)
  // Simpler approach:
  // "**** **** **** " ++ cardNum[-4 to -1]

fun isEmpty(val) = (val == null) or (sizeOf(val as String) == 0)

fun toSentenceCase(s) = (upper(s[0])) ++ (lower(s[1 to -1]))

Importing the Module

%dw 2.0
output application/json
import * from dwl::CommonFunctions
---
{
  "card":    maskCreditCard(payload.cardNumber),
  "name":    toSentenceCase(payload.customerName),
  "hasNote": !isEmpty(payload.note)
}

Recursive Functions

DataWeave functions can call themselves recursively. This is useful for processing nested tree structures like organization hierarchies or category trees.

%dw 2.0
output application/json
fun flattenTree(node) =
  if (node.children?)
    [node.name] ++ flatten(node.children map flattenTree($))
  else
    [node.name]
---
flattenTree(payload)

// Input: { name: "Root", children: [
//   { name: "A", children: [{ name: "A1" }, { name: "A2" }] },
//   { name: "B" }
// ]}
// Output: ["Root", "A", "A1", "A2", "B"]

When to Use Functions

Write a function whenever the same logic appears more than once in a DataWeave script. Write a module function whenever the same logic appears in more than one flow. Keep functions short and focused — each function should do one thing well. Name functions clearly so the next developer reading your code understands what each function does without needing a comment.

Leave a Comment

Your email address will not be published. Required fields are marked *