%dw 2.0
output application/json
var msg = "Hello"
var msg2 = (x = "ignore") -> "hello"
var toUpper = (aString) -> upper(aString)
var combined = (function, msg="universe") -> function(msg ++ " WORLD")
---
[
msg: msg,
msg2: msg2(),
toUpper: toUpper(msg),
combined: combined(toUpper, "hello"),
combined2: combined(((x) -> lower(x) ++ " Today"), msg)
]
DataWeave Variables
DataWeave is a functional programming language in which variables behave just like functions. DataWeave uses eager evaluation for variables and function parameters. In addition, DataWeave variables are immutable. Before you begin, note that DataWeave version 2 is for Mule 4 apps. For a Mule 3 app, refer to the DataWeave version 1 documentation set in the Mule 3.9 documentation. For other Mule versions, you can use the version selector for the Mule Runtime table of contents.
A variable is assigned a value, which is either a constant (such as var msg = "hello"
) or a lambda expression such as () → "hello"
.
DataWeave 1.0 variables are described in the DataWeave 1.2 documentation for Mule 3. |
DataWeave Variable Assignment
Here are some examples of DataWeave version 2 variable assignments:
The previous script results in this output:
[
{
"msg": "Hello"
},
{
"msg2": "hello"
},
{
"toUpper": "HELLO"
},
{
"combined": "HELLO WORLD"
},
{
"combined2": "hello world Today"
}
]
In these examples:
-
The
msg
var is assigned to a constant. -
msg2
is assigned to an expression that maps to a constant, somsg2()
behaves the same way asmsg
, without the()
. -
The
toUpper
variable maps an input parameter to the DataWeaveupper
function. So it is used like a more traditional function in other languages astoUpper(aString)
. -
The
combined
variable accepts a function as an input parameter, then applies that function name to the secondmsg
argument. The secondmsg
argument is optional because a default valueuniverse
is specified.
The result of the expression combined(toUpper, " world")
is to apply the toUpper
function defined earlier in the header to the msg
parameter value world
. The supplied second argument world
overrides the msg="universe"
default value, so the result is HELLO WORLD
. The expression combined(toUpper)
, which omits the second argument, uses the default msg
value to return "combined": "UNIVERSE WORLD"
.
The combined2: combined(x) → lower(x) ++ " Today", msg)
defines the lambda expression that you can reuse in different contexts. In the example, combined2
key defines the expression “in place” at the time the function is called.
Note that these types of “in place” expressions are called closures in languages like JavaScript.
DataWeave includes syntactic sugar to make it easier to access lambda expressions that are assigned to a variable as functions. To do this, you replace the var
directive with the fun
directive, and replace the arrow →
in the lambda expression with an equal sign (=
). You also move the lambda expression arguments next to the function name so the syntax looks like a function declaration in other procedural programming languages. This enables you to use variables as if they were functions. So the previous example can be equivalently written as:
%dw 2.0
output application/json
var msg = "Hello"
var toUpper = (aString) -> upper(aString)
var toLower = (aString) -> lower(aString)
fun msg2(optParm = "ignore") = "hello"
fun toTitle(text: String) = toLower(text[0]) ++ toUpper(text[1 to -1])
fun combined(function, msg="universe") = function(msg ++ " world")
---
[
msg: msg,
msg2: msg2(),
toUpper: toTitle(msg),
combined: combined(toUpper, msg),
combined2: combined((x) -> lower(x) ++ " today", msg)
]
This example produces the same result:
[
{
"msg": "Hello"
},
{
"msg2": "hello"
},
{
"toUpper": "hELLO"
},
{
"combined": "HELLO WORLD"
},
{
"combined2": "hello world today"
}
]
The important distinction in DataWeave is that functions are variables, and every function is just a syntactical renaming of the underlying var
syntax, which allows you to pass function names or lambda expressions as arguments to other functions. The fun
syntax allows you to access the powerful functional programming aspects of DataWeave while also being able to write simpler expressions as function calls you might be more familiar with.
Also notice that DataWeave variables (and functions) can specify any number of optional arguments by providing default values, so long as all those optional arguments are last in the argument list.
Example: Declare an Array Variable and Transform its Elements
Variables are immutable in DataWeave, however you can iterate over an array variable and apply a transformation to its elements, which can then be assigned to new variables. The following example declares two array variables, iterates over them to transform their elements, and then declares an object containing two new arrays with the transformed elements:
DataWeave Source:
%dw 2.0
import * from dw::core::Strings
output application/json
var numberArray = [1,2,3,4,5,6]
var stringArray = ["max", "astro", "einstein"]
---
{
"numberArrayUpdated" : numberArray map ((value, index) -> value * value),
"stringArrayUpdated" : stringArray map ((value, index) -> index ++ " - " ++ capitalize(value))
}
Output:
{
"numberArrayUpdated": [ 1, 4, 9, 16, 25, 36 ],
"stringArrayUpdated": [ "0 - Max", "1 - Astro", "2 - Einstein" ]
}
Naming Rules for Variables
You can declare any variable name that is a valid identifier. See Rules for Declaring Valid Identifiers for more details.
Variable Scopes
You can initialize and use both global and local variables in DataWeave scripts.
-
Global variables are initialized in the header of the DataWeave script and can be referenced by name from anywhere in the body of a DataWeave script.
The header of a DataWeave script accepts a
var
directive that initializes a variable, for example:var language='Español'
. You can declare multiple global variables on separate lines in the header. -
Local variables are initialized in the body of the DataWeave script and can be referenced by name only from within the scope of the expression where they are initialized.
The syntax for initializing a local variable looks like this:
do { [type <name> = <type expression>]* [var <name> = <expression>]* [fun <name>(<params>*) = <expression>]* [ns <name> <nsUri>]* --- <body> }
Note that DataWeave variables cannot be reassigned. They are also distinct from variables that are part of the Mule message (such as target variables). DataWeave variables do not persist beyond the scope of the script in which they are initialized.
Example: Global DataWeave Variables
This example defines a do
operation that initializes a language
variable with the constant value Español
and returns that constant value. The body of the DataWeave script calls the
do
operation using the variable myVar
, which populates the <language/>
element in the
XML output with the value Español
.
%dw 2.0
output application/xml
var myVar = do {
var language = "Español"
---
language
}
---
{
document: {
language: myVar,
text: "Hola mundo"
}
}
<?xml version='1.0' encoding='UTF-8'?>
<document>
<language>Español</language>
<text>Hola mundo</text>
</document>
Example: Local DataWeave Variables
To initialize local variables, you can use either literal expressions, variable reference expressions, or functional expressions. These expressions can reference any other local variables within their scope or any input or global variables.
As a best practice, declare local variables within do
scopes (see Flow Control in DataWeave). The alternative method of declaring a scope with the using
keyword is no longer recommended and available only to provide compatibility.
You can only reference a local variable by name from within the scope of the expression that initializes it. The declaration can be prepended to any literal expression. The literal delimits the scope of the variable, so you cannot reference any variable outside of its scope.
The examples that follow show initialization of local variables.
The following example sets the local variable myVar
in a do
scope. It calls do
from the body of the DataWeave script:
%dw 2.0
output application/json
---
do {
var myVar = 2
---
3 + myVar
}
The result is 5
.
The following example sets the local variable myVar
in a do
scope and uses it to set the value of the second element in the array to 2
:
%dw 2.0
output application/json
---
do {
var myVar = 2
---
[1, myVar, 3]
}
The result is [ 1, 2, 3]
In the following example, references to all the variables are valid. fn
and ln
are defined and called within the do
scope. The global myVar
variable is also accessible from that scope.
%dw 2.0
var myVar = 1234
var myDo = do {
var fn = "Annie"
var ln = "Point"
---
{
id : myVar,
firstname : fn,
lastname : ln
}
}
output application/xml
---
{ person : myDo }
<?xml version='1.0' encoding='UTF-8'?>
<person>
<id>1234</id>
<firstname>Annie</firstname>
<lastname>Point</lastname>
</person>
The following example produces an error because fromDoScope
is referenced from outside the scope of do
. As a consequence, the concatenation operation (++
) cannot append the name-value pair to the collection.
%dw 2.0
var myVar = 1234
var myDo = do {
var fn = "Annie"
var ln = "Point"
var fromDoScope = "Platform"
---
{
id : myVar,
firstname : fn,
lastname : ln
}
}
output application/xml
---
{
person : myDo ++ { "outsideDoScope" : fromDoScope }
}
The invalid example returns this error:
Unable to resolve reference of fromDoScope.
The following example passes the string HELLO
to the test
function defined in the header. The do
scope accepts the string, converts it to lowercase, and then concatenates that string to the suffix
variable, which is also defined in the header of the scope.
%dw 2.0
fun test(param1: String) = do {
var suffix = "123"
fun innerTest(str: String) = lower(str)
---
innerTest(param1 ++ suffix)
}
output application/json
---
test("HELLO")
The result is "hello123"
.
Variables Assigned as Lambda Expressions
When a variable is assigned a lambda expression, it behaves just like a function. Like a function, the lambda expression for a variable assignment can include parameters that can be used in the right-hand side expression, such as (string) → upper(string)
, which will convert any string to uppercase.
Other variables can also be passed as arguments to another variable’s lambda expression. This example shows how the toUpper
variable’s lambda expression can be passed by name into the addSuffix
variable’s lambda expression.
%dw 2.0
output application/json
var toUpper = (aString) -> upper(aString)
var addSuffix = (msg, aFunction, suffix) -> aFunction(msg ++ suffix)
---
addSuffix("hello", toUpper, " world") //result is "HELLO WORLD"