MuleSoft DataWeave - A Powerful Language For Data Transformations
Enterprise integration is not only a connectivity problem. Applications frequently represent the same business information in different structures and formats, making data transformation a central concern in integration design.
Data transformation converts information from a source representation into the structure expected by a target system. MuleSoft introduced DataWeave as its language for querying and transforming data within Anypoint Platform. It supports transformations ranging from straightforward field mappings to normalization, grouping, joins, deduplication, pivoting, and filtering across formats such as XML, JSON, CSV, Java objects, and EDI.
This article introduces the structure of DataWeave and walks through an example that transforms JSON input into Java objects and then into XML.
Version context: This article was originally written for the Mule 3/DataWeave generation of Anypoint Studio. The examples remain useful for understanding the transformation model, but syntax and tooling have evolved in later Mule and DataWeave versions.
DataWeave Structure
A DataWeave transformation has two conceptual sections: a header, which defines transformation directives, and a body, which describes the output structure. In the DataWeave version used by this example, the sections are separated by three dashes (---).
Header
The header contains high-level transformation directives. Depending on the transformation, these can define:
- DataWeave version
- Input types and sources
- Output type
- Namespaces
- Constants
- Reusable functions
Body
The body contains the expression that produces the output. Regardless of the source and destination formats, DataWeave provides a consistent model for describing the transformed result.
Common output structures include:
- Objects — collections of key-value pairs
- Arrays — ordered sequences of values
- Simple values — scalar literals such as strings, numbers, and booleans
Example: JSON → Java → XML
The following example demonstrates a multi-stage transformation. JSON input is first mapped into Java domain objects and those objects are then transformed into XML.
Step 1: Define the JSON Schema
Employee JSON Schema
{
"title": "Employee Schema",
"type": "object",
"properties": {
"emp_id": {
"type": "integer"
},
"first_name": {
"type": "string"
},
"last_name": {
"type": "string"
},
"preferred_first_name": {
"type": "string"
},
"preferred_last_name": {
"type": "string"
},
"dob": {
"type": "string"
},
"active": {
"type": "string"
},
"addresses": {
"type": "array",
"items": {
"type": "object",
"properties": {
"address_line1": {
"type": "string"
},
"address_line2": {
"type": "string"
},
"city": {
"type": "string"
},
"state": {
"type": "string"
},
"zip_code": {
"type": "string"
},
"country": {
"type": "string"
}
},
"required": [
"address_line1",
"city",
"state",
"zip_code",
"country"
]
}
},
"contacts": {
"type": "array",
"items": {
"type": "object",
"properties": {
"home": {
"type": "string"
},
"cell": {
"type": "string"
},
"fax": {
"type": "string"
},
"primary_email": {
"type": "string"
},
"secondary_email": {
"type": "string"
}
}
}
}
},
"required": [
"emp_id",
"first_name",
"last_name",
"dob",
"active"
]
}Step 2: Define the XML Schema
Employee XML Schema
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://www.example.org/xml_schema_employee/"
targetNamespace="http://www.example.org/xml_schema_employee/">
<element name="Employee" type="tns:Employee"></element>
<complexType name="Employee">
<sequence>
<element name="empId" type="integer" maxOccurs="1" minOccurs="1">
</element>
<element name="firstName" type="string" maxOccurs="1"
minOccurs="1">
</element>
<element name="middleName" type="string" maxOccurs="1"
minOccurs="0">
</element>
<element name="lastName" type="string" maxOccurs="1"
minOccurs="1">
</element>
<element name="preferredFullName" type="string" maxOccurs="1"
minOccurs="0">
</element>
<element name="dateOfBirth" type="string" maxOccurs="1"
minOccurs="1">
</element>
<element name="isActive" type="boolean" maxOccurs="1"
minOccurs="1">
</element>
<element name="address" type="tns:Address" maxOccurs="unbounded"
minOccurs="0">
</element>
<element name="contact" type="tns:Contact" maxOccurs="unbounded"
minOccurs="0">
</element>
</sequence>
</complexType>
<complexType name="Address">
<sequence>
<element name="line1" type="string" maxOccurs="1" minOccurs="1">
</element>
<element name="line2" type="string" maxOccurs="1" minOccurs="0">
</element>
<element name="city" type="string" maxOccurs="1" minOccurs="1">
</element>
<element name="state" type="string" maxOccurs="1" minOccurs="1">
</element>
<element name="zip" type="string" maxOccurs="1" minOccurs="1">
</element>
<element name="country" type="string" maxOccurs="1"
minOccurs="1"></element>
</sequence>
</complexType>
<complexType name="Contact">
<sequence>
<element name="home" type="string" maxOccurs="1"
minOccurs="0">
</element>
<element name="mobile" type="string" maxOccurs="1"
minOccurs="0">
</element>
<element name="fax" type="string" maxOccurs="1"
minOccurs="0">
</element>
<element name="email" type="tns:Email" maxOccurs="1"
minOccurs="0">
</element>
</sequence>
</complexType>
<complexType name="Email">
<sequence>
<element name="primary" type="string" maxOccurs="1"
minOccurs="0">
</element>
<element name="secondary" type="string" maxOccurs="1" minOccurs="0"></element>
</sequence>
</complexType>
</schema>
Step 3: Create the Java Domain Classes
Employee.java
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class Employee implements Serializable {
private static final long serialVersionUID = 830974489967994125L;
private Integer employeeId;
private String firstName;
private String middleName;
private String lastName;
private String preferredFullName;
private Date dateOfBirth;
private boolean active;
private List<Address> addresses;
private List<Contact> contacts;
public Integer getEmployeeId() {
return employeeId;
}
public void setEmployeeId(Integer employeeId) {
this.employeeId = employeeId;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getMiddleName() {
return middleName;
}
public void setMiddleName(String middleName) {
this.middleName = middleName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Date getDateOfBirth() {
return dateOfBirth;
}
public void setDateOfBirth(Date dateOfBirth) {
this.dateOfBirth = dateOfBirth;
}
public boolean isActive() {
return active;
}
public void setActive(boolean active) {
this.active = active;
}
public String getPreferredFullName() {
return preferredFullName;
}
public void setPreferredFullName(String preferredFullName) {
this.preferredFullName = preferredFullName;
}
public List<Address> getAddresses() {
if (addresses == null) {
addresses = new ArrayList<Address>();
}
return addresses;
}
public void setAddresses(List<Address> addresses) {
this.addresses = addresses;
}
public List<Contact> getContacts() {
if (contacts == null) {
contacts = new ArrayList<Contact>();
}
return contacts;
}
public void setContacts(List<Contact> contacts) {
this.contacts = contacts;
}
}Contact.java
import java.io.Serializable;
public class Contact implements Serializable {
private static final long serialVersionUID = 8191183310915009265L;
private String homePhone;
private String cellPhone;
private String fax;
private Email email;
public String getHomePhone() {
return homePhone;
}
public void setHomePhone(String homePhone) {
this.homePhone = homePhone;
}
public String getCellPhone() {
return cellPhone;
}
public void setCellPhone(String cellPhone) {
this.cellPhone = cellPhone;
}
public String getFax() {
return fax;
}
public void setFax(String fax) {
this.fax = fax;
}
public Email getEmail() {
return email;
}
public void setEmail(Email email) {
this.email = email;
}
}Address.java
import java.io.Serializable;
public class Address implements Serializable {
private static final long serialVersionUID = -4178015379362625254L;
private String line1;
private String line2;
private String city;
private String state;
private String zipCode;
private String country;
public String getLine1() {
return line1;
}
public void setLine1(String line1) {
this.line1 = line1;
}
public String getLine2() {
return line2;
}
public void setLine2(String line2) {
this.line2 = line2;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getZipCode() {
return zipCode;
}
public void setZipCode(String zipCode) {
this.zipCode = zipCode;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
}Email.java
import java.io.Serializable;
public class Email implements Serializable {
private static final long serialVersionUID = 6412135990330505529L;
private String primary;
private String secondary;
public String getPrimary() {
return primary;
}
public void setPrimary(String primary) {
this.primary = primary;
}
public String getSecondary() {
return secondary;
}
public void setSecondary(String secondary) {
this.secondary = secondary;
}
}Step 4: Build the Mule Flow in Anypoint Studio

Step 5: Transform JSON into Java Objects
%dw 1.0
%output application/java
---
{
active: payload.active as :boolean,
addresses: payload.addresses map ((address , indexOfAddress) -> {
city: address.city,
country: address.country,
line1: address.address_line1,
line2: address.address_line2,
state: address.state,
zipCode: address.zip_code
}),
contacts: payload.contacts map ((contact , indexOfContact) -> {
cellPhone: contact.cell,
email: {
primary: contact.primary_email,
secondary: contact.secondary_email
},
fax: contact.fax,
homePhone: contact.home
}),
dateOfBirth: payload.dob as :date { format: "yyyyMMdd"},
employeeId: payload.emp_id,
firstName: payload.first_name,
lastName: payload.last_name,
preferredFullName: payload.preferred_first_name ++ " " ++ payload.preferred_last_name
} as :object {
class : "com.appnovation.dataweave.example.Employee"
}
Step 6: Transform the Java Objects into XML
%dw 1.0
%output application/xml
%namespace ns0 http://www.example.org/xml_schema_employee/
---
{
ns0#Employee: {
empId: payload.employeeId,
firstName: payload.firstName,
middleName: payload.middleName,
lastName: payload.lastName,
preferredFullName: payload.preferredFullName,
dateOfBirth: payload.dateOfBirth as :string,
isActive: payload.active,
(payload.contacts map ((contact , indexOfContact) -> {
contact: {
mobile: contact.cellPhone,
home: contact.homePhone,
fax: contact.fax,
email: {
primary: contact.email.primary,
secondary: contact.email.secondary
}
}
})),
(payload.addresses map ((address , indexOfAddress) -> {
address: {
line1: address.line1,
line2: address.line2,
city: address.city,
state: address.state,
zip: address.zipCode,
country: address.country
}
}))
}
}
Step 7: Compare the Input and Output
Input — JSON
{
"emp_id": 112233,
"first_name": "Sagar",
"last_name": "Chaudhari",
"dob": "19010101",
"preferred_first_name": "Sagar",
"preferred_last_name": "Chaudhari",
"active": true,
"addresses": [
{
"address_line1": "120 Spanish",
"address_line2": "A",
"city": "San Francisco",
"state": "California",
"zip": "94100",
"country": "USA"
},
{
"address_line1": "120 Test",
"address_line2": "B",
"city": "St Louis",
"state": "Missouri",
"zip_code": "63001",
"country": "USA"
}
],
"contacts": [
{
"home": "111-111-1111",
"cell": "222-222-2222",
"fax": "333-333-3333",
"primary_email": "a@primary.com",
"secondary_email": "b@secondary.com"
},
{
"home": "555-555-5555"
}
]
}
Output — XML
<?xml version='1.0' encoding='UTF-8' ?>
<ns0:Employee xmlns:ns0="http://www.example.org/xml_schema_employee/">
<empId>112233</empId>
<firstName>Sagar</firstName>
<middleName xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
<lastName>Chaudhari</lastName>
<preferredFullName>Sagar Chaudhari</preferredFullName>
<dateOfBirth>1901-01-01T00:00:00</dateOfBirth>
<isActive>true</isActive>
<contact>
<mobile>222-222-2222</mobile>
<home>111-111-1111</home>
<fax>333-333-3333</fax>
<email>
<primary>a@primary.com</primary>
<secondary>b@secondary.com</secondary>
</email>
</contact>
<contact>
<mobile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
<home>555-555-5555</home>
<fax xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
<email>
<primary xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
<secondary xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
</email>
</contact>
<address>
<line1>120 Spanish</line1>
<line2>A</line2>
<city>San Francisco</city>
<state>California</state>
<zip xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
<country>USA</country>
</address>
<address>
<line1>120 Test</line1>
<line2>B</line2>
<city>St Louis</city>
<state>Missouri</state>
<zip>63001</zip>
<country>USA</country>
</address>
</ns0:Employee>
Why a Transformation Language Helps
A dedicated transformation language can keep mapping logic separate from general application code. For integration applications, that separation makes complex mappings easier to read, maintain, test, and evolve as source or target contracts change.
DataWeave also provides a common transformation approach across multiple data representations, reducing the need to implement a different parsing and serialization strategy for every integration.
Takeaway
The important idea behind DataWeave is broader than format conversion. It provides a declarative layer for expressing how one system's data model maps to another. That becomes especially valuable in enterprise integration, where transformations often include structural changes, filtering, normalization, and business-specific mapping rules in addition to converting JSON to XML or another format.