%dw 2.0
output application/json
---
{ "mathOperators" : [
{ "2 + 2" : (2 + 2) },
{ "2 - 2" : (2 - 2) },
{ "2 * 2" : (2 * 2) },
{ "2 / 2" : (2 / 2) }
]
}
DataWeave Operators
DataWeave 2.0 supports several operators, including mathematical operators, equality operators, and operators such as prepend, append and update. Before you begin, note that DataWeave 2.0 is for Mule 4 apps. For Mule 3 apps, refer to DataWeave Operators in the Mule 3.9 documentation. For other Mule versions, you can use the version selector for the Mule Runtime table of contents.
Mathematical Operators
DataWeave 2.0 supports the most common mathematical operators:
Operator | Description |
---|---|
|
For addition. |
|
For subtraction. |
|
For multiplication. |
|
For division. |
The following example uses mathematical operators:
{
"mathOperators": [
{ "2 + 2": 4 },
{ "2 - 2": 0 },
{ "2 * 2": 4 },
{ "2 / 2": 1.0 }
]
}
Equality and Relational Operators
DataWeave 2.0 supports the following equality and relational operators:
Operator | Description |
---|---|
|
For less than. |
|
For greater than. |
|
For less than or equal to. |
|
For greater than or equal to. |
|
For equal to. |
|
Equality operator that tries to coerce one value to the type of the other when the types are different. |
Note that you can negate these operators by using the logical operator, not
.
The following example uses relational operators:
%dw 2.0
output application/json
---
{ "relational" : [
{ "1 < 1" : (1 < 1) },
{ "1 > 2" : (1 > 2) },
{ "1 <= 1" : (1 <= 1) },
{ "1 >= 1" : (1 >= 1) }
]
}
{ "relational": [
{ "(1 < 1)": false },
{ "(1 > 2)": false },
{ "(1 <= 1)": true },
{ "(1 >= 1)": true }
]
}
Note that if the operands of the relational operator belong to different types,
DataWeave coerces the right-side operand to the type of the left-side operand.
For example, in the expression "123" > 12
DataWeave coerces 12
(a Number type)
to "12"
(a String type) and compares each String value lexicographically.
In the expression 123 > "12"
, DataWeave coerces the String value "12"
to the Number value 12
and compares the numbers.
These examples use equality operators:
%dw 2.0
output application/dw
---
{ "equality" :
[
(1 == 1),
(1 == 2),
("true" == true),
("true" ~= true),
(['true'] ~= [true]),
('1' ~= 1)
]
}
{
equality: [ true, false, false, true, true, true ]
}
Logical Operators
DataWeave 2.0 supports the following logical operators:
Operator | Description |
---|---|
|
Negates the result of the input. See also, |
|
Negates the result of the input. See also, |
|
Returns |
|
Returns |
Though the semantics of not and ! are the same, their precedence
differs. not true or true is executed as not (true or true) ,
so it returns false , whereas !true or true returns true because
the ! only applies to the first true . !(true or true) returns
false .
|
The following examples use logical operators:
%dw 2.0
output application/json
var myArray = [1,2,3,4,5]
var myMap = myArray map not (($ mod 2) == 0)
---
{
"not" : [
"notTrue" : not true,
"notFalse" : not false,
"myMapWithNot" : myMap
],
"and" : [
"andTrueFalse" : true and false,
"andIsTrue" : (1 + 1 == 2) and (2 + 2 == 4),
"andIsFalse" : (1 + 1 == 2) and (2 + 2 == 2)
],
"or" : [
"orTrueFalse" : true or false,
"orIsTrue" : (1 + 1 == 2) or (2 + 2 == 2),
"orIsFalse" : (1 + 1 == 1) or (2 + 2 == 2)
],
"!-vs-not" : [
"example-!" : (! true or true),
"example-not" : (not true or true)
]
}
Note that myMap
iterates through the items in a list (myArray
) and
determines whether the modulo (mod
) expression does not evaluate to 0
when
applied to each given item.
{
"not": [
{ "notTrue": false },
{ "notFalse": true },
{ "myMapWithNot": [ true, false, true, false, true ] }
],
"and": [
{ "andTrueFalse": false },
{ "andIsTrue": true },
{ "andIsFalse": false }
],
"or": [
{ "orTrueFalse": true },
{ "orIsTrue": true },
{ "orIsFalse": false }
],
"!-vs-not": [
{ "example-!": true },
{ "example-not": false }
]
}
Note that not
works in expressions such as not (true)
, but not(true)
(without the space) does not work.
You can use logical operators together. The following example uses:
-
or not
as defined in theorNot
expression -
and not
inandNot
-
not
andand not
innotWithAndNot
.
%dw 2.0
output application/json
var orNot = if (1 + 1 == 4 or not 1 == 2) {"answer": "foo"}
else {"answer": "nope"}
var andNot = if (1 + 1 == 2 and not 1 == 2) {"answer": "bar"}
else {"answer": "nope"}
var notWithAndNot = if (not (1 + 1 == 2 and not 1 == 1)) {"answer": "foobar"}
else {"answer": "nope"}
---
{ "answers" :
[
orNot,
andNot,
notWithAndNot
]
}
{
"answers": [
{ "answer": "foo" },
{ "answer": "bar" },
{ "answer": "foobar" }
]
}
Prepend, Append, and Remove Operators for Arrays
DataWeave 2.0 supports operators for appending and prepending items within an array:
Operator | Description |
---|---|
|
Prepends data on the left-hand side of the operator to items in the
array on the right-hand side. For example, |
|
Appends data on the right-hand side of the operator to items in the
array on the left-hand side. For example, |
|
Appends data on the right-hand side of the operator to items in the
array on the left-hand side. For example, |
|
Removes a specified element of any supported type from an array. |
The following examples show uses of prepend, append, and remove operators on arrays:
%dw 2.0
output application/json
---
{
"prepend-append" : [
// Array on right side when prepending.
{ "prepend" : 1 >> [2] },
{ "prepend-number" : 1 >> [1] },
{ "prepend-string" : "a" >> [1] },
{ "prepend-object" : { "a" : "b"} >> [1] },
{ "prepend-array" : [1] >> [2, 3] },
{ "prepend-binary" : (1 as Binary) >> [1] },
{ "prepend-date-time" : |23:57:59Z| >> [ |2017-10-01| ] },
// Array is on left side when appending.
{ "append-number" : [1] << 2 },
{ "append-string" : [1] << "a" },
{ "append-object" : [1] << { "a" : "b"} },
{ "append-array" : [1,2] << [1, 2, 3] },
{ "append-binary" : [1] << (1 as Binary) },
{ "append-date-time" : [ |2017-10-01| ] << |23:57:59Z| },
{ "append-object-to-array" : [1,2] << {"a" : "b"} },
{ "append-array-to-array1" : ["a","b"] << ["c","d"] },
{ "append-array-to-array2" : [["a","b"],["c","d"]] << ["e","f"] },
// + always appends within the array
{ "append-with-+" : [1] + 2 },
{ "append-with-+" : [2] + 1 },
{ "removeNumberFromArray" : ( [1,2,3] - 2 ) },
{ "removeObjectFromArray" : ( [ {a : "b"}, {c : "d"} , { e : "f"} ] - { c : "d"} ) }
]
}
{
"prepend-append": [
{ "prepend": [ 1, 2 ] },
{ "prepend-number": [ 1, 1 ] },
{ "prepend-string": [ "a", 1 ] },
{ "prepend-array": [ [ 1 ], 2, 3 ] },
{ "prepend-object": [ { "a": "b" }, 1 ] },
{ "prepend-binary": [ "\u0001", 1 ] },
{ "prepend-date-time": [ "23:57:59Z", "2017-10-01" ] },
{ "append-number": [ 1, 2 ] },
{ "append-string": [ 1, "a" ] },
{ "append-object": [ 1, { "a": "b" } ] },
{ "append-array": [ 1, 2, [ 1, 2, 3 ] ] },
{ "append-binary": [ 1, "\u0001" ] },
{ "append-date-time": [ "2017-10-01", "23:57:59Z" ] },
{ "append-object-to-array": [ 1, 2, { "a": "b" } ] },
{ "append-array-to-array1": [ "a", "b", ["c","d"] ] },
{ "append-array-to-array2": [ ["a","b"], ["c","d"], ["e","f"] ] },
{ "append-with-+": [ 1, 2] },
{ "append-with-+": [ 2, 1] },
{ "removeNumberFromArray": [ 1, 3 ] },
{ "removeObjectFromArray": [ { "a": "b" }, { "e": "f" } ] }
]
}
Scope and Flow Control Operators
DataWeave 2.0 supports operators that control the flow and scope of expressions:
Operator | Description |
---|---|
|
Creates a scope in which new variables, functions, annotations, or namespaces can be declared and used. The syntax is similar to a mapping in that it is composed of a header and body separated by |
|
Replaced by |
Operator | Description |
---|---|
|
An |
|
An |
Update Operator
DataWeave supports the update
operator, which enables you to update specified fields of a data structure with new values.
Introduced in DataWeave 2.3.0. Supported by Mule 4.3 and later.
The following example shows use of the update operator, assume that you receive the next object as input:
{
"name": "Ken",
"lastName":"Shokida",
"age": 30
}
Prior to Mule 4.3, to increase the age value by one without using the update operator or recreating the object again, the way to accomplish this was using the following DataWeave syntax:
payload mapObject ((value,key) ->
if(key as String == "age")
{(key): value as Number + 1}
else
{(key): value} )
Using the update operator it is simplified to:
payload update {
case age at .age -> age + 1
}
As shown in the previous example with the update operator there is no need for casting or going through all the key value pairs. The update syntax is as follows:
<value_to_update> update {
case <variable_name> at <update_expression>[!]? [if(<conditional_expression>)]? -> <new value>
...
}
-
value_to_update
represents the original value that is going to be updated. -
update_expression
is the selector expression that is going to match a given value of thevalue_to_update
-
variable_name
is the name of the variable that is going to bind to the matchedupdate_expression
existing value. -
new_value
is the expression with the new value. -
[if(<conditional_expression>)]?
Ifconditional_expression
is true then the value is update. This section is optional and only required for Optional update. -
[!]
marks the selector as an upsert. When marking the expression with!
if the expression doesn’t match anything, the update operator creates all the required elements and inserts the new value. -
update_expression
supports multiplecase
expressions.
The update operator doesn’t mutate the existing value but rather create a new one with the updated expressions. |
Selector Expressions
Use selector expressions with the update operator to specify which fields should be updated.
Value Selector
This matching selector allows to match any field value of a given object.
The following example updates a field at the root level and a field in a nested level using the value selector:
{
"name": "Ken",
"lastName":"Shokida",
"age": 30,
"address": {
"street": "Amenabar",
"zipCode": "AB1234"
}
}
%dw 2.0
output application/json
---
payload update {
case age at .age -> age + 1
case s at .address.street -> "First Street"
}
{
"name": "Ken",
"lastName": "Shokida",
"age": 31,
"address": {
"street": "First Street",
"zipCode": "AB1234"
}
}
Index Selector
This matching selector allows to match any array by its index.
The following example updates an element that is at the first location of the array:
{
"name": "Ken",
"lastName":"Shokida",
"age": 30,
"addresses": [{
"street": "Amenabar",
"zipCode": "AB1234"
}]
}
%dw 2.0
output application/json
---
payload update {
case s at .addresses[0] -> {
"street": "Second Street",
"zipCode": "ZZ123"
}
}
{
"name": "Ken",
"lastName": "Shokida",
"age": 30,
"addresses": [
{
"street": "Second Street",
"zipCode": "ZZ123"
}
]
}
Attribute Selector
This matching selector allows to match any attribute value.
The following example updates an attribute value and changes it to upper case:
<user name="leandro"/>
%dw 2.0
output application/json
---
payload update {
case name at .user.@name -> upper(name)
}
<?xml version='1.0' encoding='UTF-8'?>
<user name="LEANDRO"/>
Dynamic Selector
Any of the given selectors can use an expression to make it dynamic.
The following example selects and updates a value where the field to be updated is in a variable and not hardcoded. In this case from the variable theFieldName
with value name
:
{
"name": "Ken",
"lastName":"Shokida"
}
%dw 2.0
output application/json
var theFieldName = "name"
---
payload update {
case s at ."$(theFieldName)" -> "Shoki"
}
{
"name": "Shoki",
"lastName": "Shokida"
}
Conditional Update
The update operator has a syntax to write a conditional update if you only want to modify a field under a given condition.
The following example updates the category based on the name of the user:
[{"name": "Ken", "age": 30}, {"name": "Tomo", "age": 70}, {"name": "Kajika", "age": 10}]
%dw 2.0
output application/json
---
payload map ((user) ->
user update {
case name at .name if(name == "Ken") -> name ++ " (Leandro)"
case name at .name if(name == "Tomo") -> name ++ " (Christian)"
}
)
[
{
"name": "Ken (Leandro)",
"age": 30
},
{
"name": "Tomo (Christian)",
"age": 70
},
{
"name": "Kajika",
"age": 10
}
]
Upserting
The update
operator enables you to insert a field if it is not present by using the !
symbol at the end of the selector expression. When the field is not present the value null
is going to be bound to the variable.
The following example updates the category based on the name of the user:
[{"lastName": "Doe"}, {"lastName": "Parker", "name": "Peter" }]
%dw 2.0
output application/json
---
payload map ((user) ->
user update {
case name at .name! -> if(name == null) "JOHN" else upper(name)
}
)
[
{
"lastName": "Doe",
"name": "JOHN"
},
{
"lastName": "Parker",
"name": "PETER"
}
]
Sugar Syntax
The update operator allows to write a shorter version syntax to avoid some boilerplate code by using a default variable named $
.
The following example uses the same Value selector example but using simpler syntax:
{
"name": "Ken",
"lastName":"Shokida",
"age": 30,
"address": {
"street": "Amenabar",
"zipCode": "AB1234"
}
}
%dw 2.0
output application/json
---
payload update {
case .age -> $ + 1
case .address.street -> "First Street"
}
{
"name": "Ken",
"lastName": "Shokida",
"age": 31,
"address": {
"street": "First Street",
"zipCode": "AB1234"
}
}