If you've spent any time writing MuleSoft integrations, you know the feeling: you're staring at a DataWeave transformation, the payload is nested three levels deep, half the fields are nullable, and your deadline was yesterday.
I've been there. After building hundreds of integrations, I compiled the patterns I reach for most into an open-source repository of 80+ production-ready DataWeave patterns. Here are the 10 you'll use the most.
1. Filter by Condition
The problem: You need to extract a subset of records — active users, in-stock products, orders above a threshold.
The pattern:
%dw 2.0
output application/json
---
payload filter (employee) -> employee.active == true
Shorthand alternative:
payload filter $.active == true
Simple, but critical. Every integration filters data. Using the $ shorthand keeps it concise when the predicate is straightforward.
2. GroupBy for Aggregation
The problem: Your API returns a flat list of orders, but the downstream system expects them grouped by customer or region.
The pattern:
%dw 2.0
output application/json
---
payload groupBy $.department
This produces an object where each key is a department name and the value is an array of matching records. Need nested grouping? Chain it:
payload groupBy $.region mapObject (employees, region) ->
(region): employees groupBy $.department
3. Flatten Nested Arrays
The problem: You've mapped over parent records and their children, and now you have an array of arrays instead of a flat list.
The pattern:
%dw 2.0
output application/json
---
payload flatMap (order) ->
order.lineItems map (item) -> {
orderId: order.id,
sku: item.sku,
quantity: item.quantity
}
The key insight: flatMap maps and flattens in one step. Using map here would give you [[...], [...]] — a nested mess. flatMap gives you [..., ...].
4. Null-Safe Defaults
The problem: Integration payloads are inherently unreliable. A field that existed yesterday might be null today, and your transformation crashes.
The pattern:
%dw 2.0
output application/json
---
{
name: payload.customer.name default "Unknown",
email: payload.customer.email default "noreply@example.com",
tier: payload.customer.loyalty.tier default "STANDARD"
}
The default operator is your best friend. It handles the entire null chain — if payload.customer is null, the whole expression resolves to the default instead of throwing an error.
Anti-pattern to avoid:
// Don't do this — verbose and error-prone
name: if (payload.customer.name != null) payload.customer.name else "Unknown"
5. XML to JSON with Attributes
The problem: You're consuming a SOAP service or processing B2B XML, and you need to extract attributes, handle repeating elements, and coerce types — all in one transformation.
The pattern:
%dw 2.0
output application/json
---
{
orderId: payload.PurchaseOrder.@orderNumber,
date: payload.PurchaseOrder.@orderDate,
items: payload.PurchaseOrder.Items.*Item map (item) -> {
sku: item.@sku,
name: item.ProductName,
quantity: item.@quantity as Number,
price: item.Price as Number
}
}
Three things to remember:
-
@accesses XML attributes -
.*Itemhandles repeating elements (the #1 XML bug in MuleSoft projects — using.Itemonly returns the first one) - Always cast with
as Number— XML values are always strings
6. Object Key Manipulation
The problem: The source system uses camelCase keys but your target expects snake_case, or you need to dynamically rename, remove, or add keys.
The pattern — rename keys:
%dw 2.0
output application/json
---
payload mapObject (value, key) -> {
(lower(key) replace /([A-Z])/ with "_$1"): value
}
Remove specific keys:
payload mapObject (value, key) ->
if (["password", "ssn", "token"] contains (key as String))
{}
else
{(key): value}
mapObject is the Swiss army knife for object transformation — it gives you access to both keys and values for any manipulation you need.
7. CSV to Structured JSON
The problem: You receive a flat CSV file and need to transform it into structured JSON with proper types and nested objects.
The pattern:
%dw 2.0
output application/json
---
payload map (row) -> {
employee: {
id: row.emp_id as Number,
name: row.first_name ++ " " ++ row.last_name,
active: row.status == "ACTIVE"
},
department: row.dept_code,
salary: row.annual_salary as Number
}
The critical gotcha: every CSV field is a string. If you don't explicitly cast with as Number or as Date, you'll pass string values downstream and break validation on the target system.
8. Recursive Transformation
The problem: You need to transform data at every level of a deeply nested structure — mask PII fields, rename keys, or strip nulls regardless of depth.
The pattern:
%dw 2.0
output application/json
fun transform(data: Any): Any =
data match {
case obj is Object -> obj mapObject (v, k) ->
{(k): transform(v)}
case arr is Array -> arr map transform($)
case str is String -> upper(str)
else -> data
}
---
transform(payload)
This uses pattern matching (match/case) to handle each data type differently and recurse into nested structures. Replace upper(str) with whatever transformation you need — masking, key renaming, null stripping.
Important: Add @TailRec annotation for production use to prevent stack overflow on deeply nested payloads.
9. Salesforce to SAP Mapping
The problem: You're building an enterprise CRM-to-ERP integration and need to map Salesforce Account objects to SAP IDoc format with field translation, code lookups, and strict formatting.
The pattern:
%dw 2.0
output application/json
var industryMap = {
"Technology": "TECH",
"Healthcare": "HLTH",
"Finance": "FINA",
"Manufacturing": "MANU"
}
---
payload map (acct) -> {
IDOC: {
CUSTOMER_NUMBER: acct.AccountNumber,
COMPANY_NAME: upper(acct.Name),
INDUSTRY_KEY: industryMap[acct.Industry] default "OTHR",
EMPLOYEES: acct.NumberOfEmployees as String {format: "000000"},
CONTACTS: acct.Contacts map (c) -> {
PARTNER_NAME: c.LastName ++ ", " ++ c.FirstName,
EMAIL: c.Email default "",
PHONE: c.Phone default ""
}
}
}
This showcases lookup maps for field translation, string formatting with number padding, default for nullable fields, and nested array mapping — all patterns you'll need in any enterprise integration.
10. Error Response Builder
The problem: You need a consistent error response format across all your API endpoints, with proper HTTP status mapping and sanitized error details.
The pattern:
%dw 2.0
output application/json
fun buildError(code: Number, message: String, detail: String) = {
error: {
code: code,
message: message,
detail: detail,
timestamp: now() as String {format: "yyyy-MM-dd'T'HH:mm:ss'Z'"}
}
}
---
buildError(
vars.httpStatus default 500,
error.description default "Internal Server Error",
error.detailedDescription default "An unexpected error occurred"
)
Wrap this in a reusable function and call it from every error handler in your Mule flows. Consistent error responses make debugging in production dramatically easier.
What's Next?
These 10 patterns are just the start. The full repository includes:
- 80+ production-ready patterns across 15 categories
- 7 reusable Exchange modules (96 utility functions with 213 MUnit tests)
- DW 2.x Cheatsheet — comprehensive quick reference (MD + PDF)
- Anti-Patterns Guide — 12 common mistakes and how to fix them
- DW 1.0 to 2.0 Migration Guide — side-by-side syntax comparisons
Every pattern uses realistic data (not toy examples), includes alternative approaches, and is tested in the DataWeave Playground.
Explore all 80+ patterns on GitHub
If this helps your MuleSoft work, give it a star — it helps other developers find it too.
What DataWeave pattern do you reach for most? Drop it in the comments — I'm always looking to add more to the collection.
Top comments (0)