Contact Us 1-800-596-4880

DataWeave Language

The DataWeave language is a powerful template engine that allows you to transform data to and from any kind of format (XML, CSV, JSON, Pojos, Maps, etc). In Anypoint Studio, this language can be used in:

This document covers basic examples, an overview, the structure of a DataWeave file and information about how to access different data from it. Below are some links for more advanced topics:

  • For a reference about all of the operators that are available for using, see DataWeave Operators

  • For a listing and details about all of the types you can use, see DataWeave Types

Basic Example

In order to show the power of DataWeave, here is a minimal example to get started. This example shows a simple mapping form JSON to XML:

Input
{
  "title": "Java 8 in Action: Lambdas, Streams, and functional-style programming",
  "author": "Mario Fusco",
  "year": 2014
}
Transform
%dw 1.0
%output application/xml
---
{
  order: {
    type: "Book",
    title: payload.title,
    details: "By " ++ payload.author ++ " (" ++ payload.year ++ ")"
  }
}
Output
<?xml version='1.0' encoding='UTF-8'?>
<order>
  <type>Book</type>
  <title>Java 8 in Action: Lambdas, Streams, and functional-style programming</title>
  <details>By Mario Fusco (2014)</details>
</order>

DataWeave File Structure

DataWeave files are divided into two sections:

  • Header - defines directives (optional)

  • Body - describes the output structure

The two sections are delimited by a three-dash separator: "---"

This is basically what a .dwl file looks like. This code describes a transformation from a JSON input to an XML output:

%dw 1.0
%output application/xml
---
{
  user: {
    name: payload.user_name,
    lastName: payload.user_lastName
  }
}

Note that the two initial lines of code compose the header, the separator then delimits it from the rest of the file, the body, where the output structure is defined.

This DataWeave example expects to receive a JSON input that is structured like the JSON example below:

 {
  "user_name": "Annie",
  "user_lastName": "Point"
 }

Upon receiving that as an input, DataWeave produces the XML output shown below:

<?xml version="1.0" encoding="UTF-8"?>
<user>
 <name>Annie</name>
 <lastName>Point</lastName>
</user>

DataWeave Header

The DataWeave header contains the directives, which define high-level information about your transformation. The structure of the header is a sequence of lines, each with its own directives. The header section ends at ---.

Through the use of the following directives, key aspects of the transformation are defined:

  • DataWeave version, for example, %dw 1.0

  • Output type, for example, %output application/xml

  • Input type, for example, %input payload application/xml

  • Namespaces to import into your transform, for example, %namespace ns0 http://mulesoft.org/tshirt-service/

  • Constants that can be referenced throughout the body, for example, %var conversionRate=13.15

  • Functions that can be called throughout the body, for example, %var toUser = (user) → {firstName: user.name, lastName: user.lastName}

All directives are declared in the header section of your DataWeave document and act on the entire scope of it.

Directives are a mechanism used to declare variables, constants and namespaces and their aliases, which are referenced in the body.

Output type directives are needed to declare the type of the output of your transform.

Input directives may optionally be used to declare additional input sources and their input types.

Version Directive

Specify the version of the DataWeave syntax that is used to interpret the transformation using the version directive.

%dw 1.0

Namespace Directive

Use this directive to specify an alias for a URI, which is specified after the alias. The directive is relevant only when either the input or the output is of type XML.

%namespace mes http://www.mulesoft.com/anypoint/SOA/message/v1.0

Output Directive

Specify the transformation output type in the following format: <content>/<type>.

Only one output type can be specified — the structure of this output is further specified in the DataWeave body.

%output application/xml

Valid types are:

Input Directive

It is not necessary to declare input directives for any of the components of the Mule Message that arrive at the DataWeave transformer (payload, flow variables, and input/outbound properties) nor for any system variables.

You likely will not need this feature as any data arriving inside the incoming Mule message gets implicitly recognized as input based on the accompanying metadata that passes along with it through the flow components. As a result, the data can be referenced and acted upon easily enough anywhere within the DataWeave body without a need to include them in the header.

Optionally specify an input source and its input type in the following format: <content>/<type>.

%input payload application/xml

Valid types are:

Define Constant Directive

You can define a constant in the header, and reference it (or its child elements, if any exist) in the DataWeave body.

%dw 1.0
%var conversionRate=13.15
%output application/json
---
{
 price_dollars: payload.price,
 price_localCurrency: payload.price * conversionRate
}

Define Function Directive

You can define a function in the header, you can then call it in any part of the DataWeave body, including arguments.

%dw 1.0
%output application/json
%var toUser = (user) -> {firstName: user.name, lastName: user.lastName}
---
{
 user: toUser(payload)
}

A function directive can be defined via %var as in the example above, or via %function

Transform
%dw 1.0
%output application/json
%function toUser(user){firstName: user.name, lastName: user.lastName}
---
{
 user: toUser(payload)
}

See Functions and Lambdas for more on this.

DataWeave Body

The body contains the expression that generates the output structure.

Regardless of the input and output types, the data model for the output is always described in standard DataWeave code, and it is this model that the input is transformed into.

The data model of the produced output could consist of three different types of data:

  1. Simple Values

  2. Arrays: Represented as a sequence of comma separated values

  3. Objects: Represented as collection of key value pairs

When you write code in the DataWeave body, you define an expression that generates one of the data types listed above, even a literal string Hello world is a valid DataWeave body.

Expressions can also be complex, meaning that they can be composed of other expressions. This can be achieved by either nesting expressions inside Arrays or Objects, or through the use of operators. In complex expressions, the result of one expression sets the context for the subsequent execution of other expressions. You just need to remember that each expression produces an Object, an Array, or a Variable. When you understand the structure of these data types are constructed from DataWeave expressions, you effectively understand how to use DataWeave.

To visualize the canonical DataWeave model of your data to get a better visual reference, set the output type of your transform to application/dw. Your transform then outputs your data as a DataWeave expression, which resembles a JSON object.

Simple Values

Simple values can be of the following types:

  • String : Double quoted ("Hello") or Single quoted ('Hello')

  • Boolean : Literals true or false

  • Number : Decimal and Integer values are supported (ex: 2.0)

  • Date : IS0-8601 enclosed by "|" (ex:|2003-10-01T23:57:59Z|)

  • Regex : Regex expression enclosed by "/" (ex:/(\d+)-(\d+)/)

Arrays

Arrays are represented as a sequence of value expressions.

Input
[ 1, 2 + 2, 3 * 3, $x ]
Transform
%dw 1.0
%output application/json
---
[ "My", "three", "words" ]

See DataWeave types for more details on arrays.

Objects

These are represented as a comma separated sequence of key: value pairs surrounded by curly brackets { }.

Transform
%dw 1.0
%output application/xml
---
myoutput:{
  name : "Jill",
  payload : payload.id + 3
  }
Output
<?xml version="1.0" encoding="UTF-8"?>
<myoutput>
  <name>Jill</name>
  <payload>5</payload>
</myoutput>

Note that both the keys and the values may be expressions.

See DataWeave types for more details on objects.

Variables

Constants

In the DataWeave header, you define constants as directives, these can then be referenced as variables in any part of your transform body, just as you do with input variables. The following creates an XML document and inserts the constant value for Language "Español" in the output language element.

Transform
%dw 1.0
%output application/xml
%var language='Español'
---
{
  document: {
    language: language,
    text: "Hola mundo"
  }
}
Output
<?xml version="1.0" encoding="UTF-8"?>
<document>
  <language>Español</language>
  <text>Hola Mundo</text>
</document>

Scoped Variables

Variables declared in the Transform’s header always have a global scope, to declare and initialize a variable with a limited scope, you can do so in any part of the transform’s body.

You can initialize these variables using literal expressions, variable reference expressions, or functional expressions. They may reference any other scoped variables or any of the input variables or constants in their initialization. The declaration and initialization can be prepended to any literal expression, but you must be aware that the literal they are prepended to delimits their scope. You cannot reference a variable outside its scope.

To declare a variable in the DataWeave body, the following syntax is supported: using (<variable-name> = <expression>) and it must be written before defining the contents of the literal that it exists in. To reference an already initialized variable, you can just call it by the name you defined for it as with any other variable, or you can also write it in the form $<variable-name>.

Consider the following examples:

Scoped to Simple Value

%dw 1.0
%output application/json
---
using (x = 2) 3 + x (1)
1 Result is simply 5

Scoped to Array literal

%dw 1.0
%output application/json
---
using (x = 2) [1, x, 3]

Scoped to Object literal

%dw 1.0
%output application/xml
---
{
  person: using (user = "Greg", gender = "male") { (1)
    name: user, (2)
    gender: gender
  }
}
1 Declaration and initialization.
2 user is a valid reference because it is within the object person for which it was declared.

Invalid Reference outside of Scope

%dw 1.0
%output application/xml
---
entry: using (firstName = "Annie", lastName = "Point") {
  person: using (user = firstName, gender = "male") {
    name: user,
    gender: gender
  },
  sn: lastName, (1)
  gen: gender (2)
}
1 The reference lastName is valid because it is within scope.
2 The reference gender is invalid because gender was declared in the person object, and this reference exists outside the scope of that object.

Expressions

DataWeave allows you to put logic in your script using expression values. All expressions in DataWeave return a value, these can be categorized into:

Operators

An operator applies a specific logic/transformation over a data-structure. Operators can be classified based on their arity as Unary, Binary or Ternary. See DataWeave Operators for a full reference.

Transform
%dw 1.0
%output application/json
---
{
  name: upper "mulesoft"
}
Output
{
  "name": "MULESOFT"
}

Selectors

A selector allows for the navigation and querying the multiple levels of a data-structure to reference a certain value or set of values. See DataWeave Selectors for a full reference.

Transform
%dw 1.0
%output application/json
---
{
  users: payload.users.*user
}

Input: XML

Input
<users>
  <user>Mariano</user>
  <user>Martin</user>
  <user>Leandro</user>
</users>

Output: JSON

Output
{
  "users": [
    "Mariano",
    "Martin",
    "Leandro"
  ]
}

Flow Control Expressions

When Otherwise

The keyword when conditionally evaluates a part of your DataWeave code, depending on if an expression evaluates to true or to false. You can make a single line conditional, or enclose a whole section in curly brackets. In case the when expression evaluates to false, its corresponding part of the code is ignored, and the code that corresponds to the otherwise expression is executed.

Transform
%dw 1.0
%output application/json
---
{
  currency: "USD"
} when payload.country == "USA"
otherwise
{
      currency: "EUR"
}

You can also chain several otherwise expressions together, like in the example below:

Transform
%dw 1.0
%output application/json
---
{
	currency: "USD"
} when payload.country =="USA"
otherwise
{
	currency: "GBP"
} when payload.country =="UK"
otherwise
{
	currency: "EUR"
}
Check the Precedence Table to see what expressions are compiled before or after this one.

Unless Otherwise

The keyword unless conditionally evaluates a part of your DataWeave code, depending on if an expression evaluates to true or to false. You can make a single line conditional, or enclose a whole section in curly brackets. In case the unless expression evaluates to true, its corresponding part of the code is ignored, and the code that corresponds to the otherwise expression is executed.

Transform
%dw 1.0
%output application/json
---
{
  currency: "EUR"
} unless payload.country == "USA"
otherwise
{
      currency: "USD"
}
Check the Precedence Table to see what expressions are compiled before or after this one.

Default

Assigns a default value in case no value is found in the input field.

Transform
%dw 1.0
%output application/json
---
{
    currency: payload.currency default "USD"
}
Check the Precedence Table to see what expressions are compiled before or after this one.

Pattern matching

Pattern matching executes on the first pattern that matches the specified expression. DataWeave supports four different types of patterns:

  • literal

  • type/traits

  • regex

  • expression

Each pattern type can be either named or unnamed. The example below is not actual DataWeave code, but rather a model for how matching works, you can see more concrete examples on each of the sections that follow:

value match {
  (<name>:)?<pattern> -> <when matched>,
  (<name>:)?<pattern> -> <when matched>,
  default -> <when none of them matched>
}
For simpler use cases where all you need is a boolean result based on if a value matches or not, see the Matches Operator.
Check the Precedence Table to see what expressions are compiled before and after this one.
Literal Pattern

Matches when the evaluated value equals a simple literal value.

Transform
%dw 1.0
%output application/json
---
a: payload.string match {
   "Emiliano" -> true,
   "Mariano" -> false
 },
 b: payload.string match {
   str: "Emiliano" -> { "matches": true, value: str },
   str: "Mariano" -> { "matches": false, value: str }
 }

Input: JSON

Input
{
  "string": "Emiliano"
}

Output: JSON

Output
{
  "a": true,
  "b": {
      "matches": true,
      "value": "Emiliano"
  }
}

In this example, the first field simply matches the value in 'payload.string' and returns a boolean, the second field performs the same match, but returns an object that contains both a boolean and a reference to the validated value.

Expression Pattern

Matches when running a certain expression over the evaluated value returns true.

Transform
%dw 1.0
%output application/json
---
{
  a: payload.string match {
    str when str == "Mariano" -> str ++ " de Achaval",
    str when str == "Emiliano" -> str ++ " Lesende"
  },
  b: payload.number match {
    n when n < 3 -> "lower",
    n when n > 3 -> "higher"
  }
}

Input: JSON

Input
{
  "string": "Emiliano",
  "number": 3.14
}

Output: JSON

Output
{
  "a": "Emiliano Lesende",
  "b": "higher"
}

In this example, the first field matches the value of 'payload.string' against two alternatives and conditionally appends a different string to it; the second field evaluates if the value in 'payload.number' is larger or smaller than 3 and returns "lower" or "higher" accordingly.

Match Type

Matches when the evaluated value is of the specified type

Transform
%dw 1.0
%output application/json
---
{
  a: payload.a match {
    :object -> "OBJECT",
    :string -> "STRING",
    :number -> "NUMBER",
    :boolean -> "BOOLEAN",
    :array -> "ARRAY",
    :null -> "NULL"
  },
  b: payload.b match {
    y is :object -> { type: "OBJECT", y: y },
    y is :string -> { type: "STRING", y: y },
    y is :number -> { type: "NUMBER", y: y },
    y is :boolean -> { type: "BOOLEAN", y: y },
    y is :array -> { type: "ARRAY", y: y },
    y is :null -> { type: "NULL", y: y }
  }
}

Input: JSON

Input
{
  "a": "Emiliano",
  "b": 3.14
}

Output: JSON

Output
{
  "a": "STRING",
  "b": {
    "type": "NUMBER",
    "y": 3.14
  }
}

In this example, the first field evaluates the type of 'payload.a' and returns a different string with the type name depending on what type it matches with (this could be easier done through the Type Of operator), the second field returns an object with the same type name as a string and a reference to the evaluated value.

Match Regex

Matches when the evaluated value fits a given regular expression

Transform
%dw 1.0
%output application/json
---
{
  a: payload.phones map ($ match {
     /\+(\d+)\s\((\d+)\)\s(\d+\-\d+)/ -> { country: $[0], area: $[1], number: $[2] },
     /\((\d+)\)\s(\d+\-\d+)/ -> { area: $[1], number: $[2] }
   }),
 b: payload.phones map ($ match {
   phone: /\+(\d+)\s\((\d+)\)\s(\d+\-\d+)/ -> { country: phone[0], area: phone[1], number: phone[2] },
   phone: /\((\d+)\)\s(\d+\-\d+)/ -> { area: phone[1], number: phone[2] }
 })
}

Input: JSON

Input
{
  "phones": [
    "+1 (415) 229-2009",
    "(647) 456-7008"
  ]
}

Output: JSON

Output
{
  "a": [
    {
      "country": "+1 (415) 229-2009",
      "area": "1",
      "number": "415"
    },
    {
      "area": "647",
      "number": "456-7008"
    }
  ],
  "b": [
    {
      "country": "+1 (415) 229-2009",
      "area": "1",
      "number": "415"
    },
    {
      "area": "647",
      "number": "456-7008"
    }
  ]
}

In this example, the payload includes two elements in an array, and in both cases the Map operator to cycle through the array. It then evaluates each element against a regular expression and outputs a different object depending on what kind of match is found.

System Values

DataWeave provides a set of values that are automatically assigned by the system.

Now

Returns the present moment in (:datetime) type.

Transform
%dw 1.0
%output application/json
---
{
  a: now,
  b: now.day,
  c: now.minutes
}
Output
{
  "a": "2015-12-04T18:15:04.091Z",
  "b": 4,
  "c": 15
}
See DataWeave Selectors for a list of possible selectors to use here.

Random

Returns a random number of type (:number) between 0 and 1

Transform
%dw 1.0
%output application/json
---
{
  price: random * 1000
}

Calling External Flows

From a DataWeave transform, you can trigger the calling of a different flow in your Mule application, and whatever the flow returns is what the expression returns.

You can do this through the following expression:

lookup(“flowName”,$)

Which takes two parameters:

  • The name of the flow that must be called

  • The payload to send to this flow, as a map

Transform
%dw 1.0
%output application/json
---
{
  a: lookup("mySecondFlow",{b:"Hello"})
}
Mule Flow
<flow name="mySecondFlow">
    <set-payload doc:name="Set Payload" value="#[payload.b + ' world!' ]"/>
</flow>
Output
{
  "a": "Hello world!"
}

Please note that only the payload returned by the invoked flow will be assigned (i.e. all other message’s properties such as flowVars and sessionVars will not be overridden when using the lookup function).

The lookup function does not support calling subflows.

Calling Global MEL Functions from DataWeave Code

If you define a global Mule Expression Language (MEL) function in your Mule project, you can then invoke it anywhere in your DataWeave code, without need for any special syntax.

To create one such global function, you must edit your Mule project’s XML file and enclose any functions that you wish to define in the following set of tags, which must be placed in the global elements section, before any of the flows are defined.

<configuration doc:name="Configuration">
     <expression-language>
         <global-functions>

         </global-functions>
     </expression-language>
 </configuration>

In this space you can use any MEL expression to define custom functions, for example:

<configuration doc:name="Configuration">
     <expression-language>
         <global-functions>
             def newUser() {
                 return ["name" : "mariano"]
             }
             def upperName(user) {
                 return user.name.toUpperCase()
             }
         </global-functions>
     </expression-language>
 </configuration>

With that in place, in the DataWeave code of your Transform Message element you can just refer to these functions. Note that the inputs and outputs of these functions can even be objects and arrays.

%dw 1.0
%output application/json
---
{
  "foo" :  newUser(),
  "bar":  upperName(newUser())
}

Even with these external functions in place, you should be able to preview the output of this transform, updated in real time as you edit it.

Read

(content :string, mimeType :string,readerOptions :object) ⇒ :any

The read function returns the result of parsing the content parameter with the specified mimeType reader.

The first argument points the content that must be read, the second is the format in which to write it. A third optional argument lists reader configuration properties.

Transform
%dw 1.0
%output application/xml
---
output: read(payload.root.xmlblock, "application/xml").foo

Input: XML

Input
<?xml version='1.0' encoding='UTF-8'?>
<root>
    <xmlblock><![CDATA[<foo>bar</foo>]]></xmlblock>
</root>

Output: XML

Output
<?xml version='1.0' encoding='UTF-8'?>
<output>bar</output>

In the example above, what was in the CDATA element isn’t parsed by the DataWeave reader by default, that’s why the read operator must be used to interpret it.

Write

(value :any, mimeType :string,writerOptions :object) ⇒ :string

The write function returns a string with the serialized representation of the value in the specified mimeType.

The first argument points to the element that must be written, the second is the format in which to write it. A third optional argument lists writer configuration properties. See Output Directive and its sub-sections for a full list of available configuration options for each different format.

Transform
%dw 1.0
%output application/xml
---
{
  output: write(payload, "application/csv", {"separator" : "|"})
}

Input: JSON

Input
[
  {
    "Name": "Mr White",
    "Email": "white@mulesoft.com",
    "Id": "1234",
    "Title": "Chief Java Prophet"
  },
  {
    "Name": "Mr Orange",
    "Email": "orange@mulesoft.com",
    "Id": "4567",
    "Title": "Integration Ninja"
  }
]

Output: XML

Output
<?xml version='1.0' encoding='US-ASCII'?>
<output>Name|Email|Id|Title
Mr White|white@mulesoft.com|1234|Chief Java Prophet
Mr Orange|orange@mulesoft.com|4567|Integration Ninja
</output>

Log

(prefix :string,value :any)

Returns the specified value and also logs the value in the DataWeave representation with the specified prefix.

Transform
%dw 1.0
%output application/json
---
{
  result: log("Logging the array",[1,2,3,4])
}
Output
{
  "result": [1,2,3,4]
}
Output to Logger
Logging the array [1,2,3,4]

Note that besides producing the expected output, it also logs it.

Precedence Table

This table lists the order in which different DataWeave expressions are compiled. The result of compiling something at one level may be used as an input for expressions in higher levels, but not vice-versa. Expressions are ordered in the table from first compiled to last.

Operator Description Level

using, all unary operators

1

As

Type Coercion expression

2

* /

Multiplicative

3

+ - >>

Additive

4

>= ⇐ < > is

Relational / Type Comparison

5

!= ~= ==

Equality evaluators

6

AND

Conditional And

7

OR

Conditional OR

8

Default Value / Pattern Matching / Binary Operators

9

Conditional Expressions

10

Closer Look at an Example Transformation

Input
<?xml version="1.0" encoding="UTF-8"?>
<note>
  <to>Tove</to>
  <from>Jani</from>
  <heading>Reminder</heading>
  <body>Don't forget me this weekend!</body>
</note>
Transform
%dw 1.0
%output application/json
%var date='01-MAR-2015'
---
{
  letter : payload,
  sent : date
}
Output as JSON
{
  "letter": { (1)
    "note": { (2)
      "to": "Tove",
      "from": "Jani",
      "heading": "Reminder", (3)
      "body": "Don't forget me this weekend!"
    }
  },
  "sent": "01-MAR-2015"  (4)
}
1 The "payload" input is parsed into an Object.
2 As previously stated, Objects are sequences of key:value pairs. Note how each element name from the XML input is parsed into a key followed by a colon : and then the value.
3 The value may be a Simple Value, as is the case of the heading field, or an object, as is the case in note #2.
4 This value arises from a variable 'date', which is defined in a directive in the DataWeave header.
Whenever you make a transformation from JSON to XML, make sure that the resulting output is valid as an XML file. Specifically, make sure that there’s a single parent tag, JSON supports having multiple elements at the highest level while XML doesn’t. Likewise, whenever you transform from XML to JSON, make sure the resulting output is valid as a JSON file. Specifically, make sure that there are no repeated keys inside the same parent. XML supports having this but JSON doesn’t.

Next Steps

  • For a reference about all of the operators that are available for the using operator, see DataWeave Operators

  • For a listing and details about all of the types you can use, see DataWeave Types

  • For details on the different formats you can process with DataWeave and the parameters you can configure for each format, see DataWeave Formats

  • For details on how you can select certain components of the incoming message, see DataWeave Selectors

  • View complete example projects that use DataWeave in the Anypoint Exchange