[ 1, 2 + 2, 3 * 3, $x ]
DataWeave Value Types
DataWeave functions essentially as a template engine that describes an output structure through the use of elements that may be of various different types.
This document covers the different types of objects you can use to construct your output.
Array
Type ⇒ ':array'
Arrays are represented as a sequences of value expressions.
Array Literal
%dw 1.0
%output application/json
---
[ "My", "three", "words" ]
Object
Type ⇒ ':object'
Objects are represented as a collection of key: value pairs.
-
Object: { 'Key' : Value }
-
Key : 'Qualified Name' 'Attributes'
-
Qualified Name: 'namespace prefix#name' where the 'namespace prefix#' part is optional
-
Name: String that represents the name.
-
Attributes: @('Qualified Name'= value,…)
Strings must be double quoted to be recognized as strings. |
Single Value Objects
If an Object has only one key:value pair, the enclosing curly brackets { } are not required:
%dw 1.0
%output application/xml
---
name: "Annie"
Conditional Elements
Objects can define conditional key: value pairs based on a conditional expression. Wrap the key:value expression between parentheses and use the when keyword with the condition.
%dw 1.0
%output application/xml
---
file: {
name: "transform",
(extension: "zip") when payload.fileSystem?
}
This example outputs an additional field called "extension" only when the fileSystem property is present in payload (this field may contain any value, not just "true").
<?xml version="1.0" encoding="UTF-8"?>
<file>
<name>transform</name>
<extension>zip</extension>
</file>
If absent:
<?xml version="1.0" encoding="UTF-8"?>
<file>
<name>transform</name>
</file>
Dynamic Elements
Dynamic elements allow you to add the result of an expression as key:value pairs of an object.
%dw 1.0
%output application/json
---
{
a: "a",
(["b","c","d"] map {'$': $})
}
{
"a": "a",
"b": "b",
"c": "c",
"d": "d"
}
Dynamic keys
In order to specify a key via an expression, the expression should be wrapped in parentheses.
%dw 1.0
%output application/json
---
{name: 'Data Weave'} mapObject {(upper $$ as :string) : $}
{
"NAME": "Data Weave"
}
Conditional Attributes
Attributes can be conditional based on a given condition. Wrap the key:value expression in parentheses and use the when keyword with the condition.
%dw 1.0
%output application/xml
---
name @((company: "Acme") when false, (transform: "Anything") when true): "DataWeave"
<?xml version='1.0' encoding='US-ASCII'?>
<name transform="Anything">DataWeave</name>
Dynamic Attributes
Dynamic attributes allow you to add the result of an expression as key:value pairs of the attributes set.
{
"company": "Mule",
"product": "DataWeave"
}
%dw 1.0
%output application/xml
---
transformation @((payload)): "Transform from anything to anything"
<?xml version='1.0' encoding='US-ASCII'?>
<transformation company="Mule" product="DataWeave">Transform from anything to anything</transformation>
String
Type ⇒ ':string'
A string can be defined by the use of double quotes or single quotes.
{
doubleQuoted: "Hello",
singleQuoted: 'Hello',
}
String interpolation
String interpolation allows you to embed variables or expressions directly in a string.
%dw 1.0
%output application/json
%var name = "Shoki"
---
{
Greeting: "Hi, my name is $name",
Sum: "1 + 1 = $(1 + 1)"
}
{
"Greeting": "Hi, my name is Shoki",
"Sum": "1 + 1 = 2"
}
Number
Type ⇒ ':number'
There is only one number type that supports both floating point and integer numbers. There is no loss of precision in any operation, the engine always stores the data in the most performant way that doesn’t compromise precision.
Dates
Dates in DataWeave follow the ISO-8601 standard and are defined between '|' characters.
The date system supports:
-
DateTime
-
Local DateTime
-
Time
-
Local Time
-
Period
-
TimeZone
-
Date
Date
Type ⇒ ':date'
Represented as 'Year'-'Month'-'Date'
The type Date has no time component at all (not even midnight).
%dw 1.0
%output application/json
---
c: |2003-10-01|
{
"c": "2003-10-01"
}
Time
Type ⇒ ':time'
Represented as 'Hour':'Minutes':'Seconds'.'Milliseconds'
%dw 1.0
%output application/json
---
c: |23:59:56|
{
"c": "23:59:56"
}
TimeZone
Type ⇒ ':timeZone'
Timezones must include a + or a - to be defined as such. |03:00| is a time, |+03:00| is a timezone.
%dw 1.0
%output application/json
---
c: |-08:00|
{
"c": "-08:00"
}
DateTime
Type ⇒ ':datetime'
Date time is the conjunction of 'Date' + 'Time' + 'TimeZone'.
%dw 1.0
%output application/json
---
a: |2003-10-01T23:57:59-03:00|
{
"a": "2003-10-01T23:57:59-03:00"
}
Local Date Time
Type ⇒ ':localdatetime'
Local date time is the conjunction of 'Date' + 'Time'.
%dw 1.0
%output application/json
---
a: |2003-10-01T23:57:59|
{
"a": "2003-10-01T23:57:59"
}
Period
Type ⇒ ':period'
Specifies a period of time. Examples |PT9M| ⇒ 9 minutes , |P1Y| ⇒ 1 Year
%dw 1.0
%output application/json
---
a: |23:59:56| + |PT9M|
{
"a": "00:08:56"
}
Date decomposition
In order to access the different parts of the date, special selectors must be used.
%dw 1.0
%output application/json
---
{
day: |2003-10-01T23:57:59Z|.day,
month: |2003-10-01T23:57:59Z|.month,
year: |2003-10-01T23:57:59Z|.year,
hour: |2003-10-01T23:57:59Z|.hour,
minutes: |2003-10-01T23:57:59Z|.minutes,
seconds: |2003-10-01T23:57:59Z|.seconds,
offsetSeconds: |2003-10-01T23:57:59-03:00|.offsetSeconds,
nanoseconds: |23:57:59.700|.nanoseconds,
milliseconds: |23:57:59.700|.milliseconds,
dayOfWeek: |2003-10-01T23:57:59Z|.dayOfWeek,
dayOfYear: |2003-10-01T23:57:59Z|.dayOfYear
}
{
"day": 1,
"month": 10,
"year": 2003,
"hour": 23,
"minutes": 57,
"seconds": 59,
"offsetSeconds": -10800,
"nanoseconds": 700000000,
"milliseconds": 700,
"dayOfWeek": 3,
"dayOfYear": 274
}
Changing the Format of a Date
To format dates and times, DataWeave supports some formatting characters
that are based on the Java 8 java.time.format
package, such as the y
, M
,
and d
in the date format yyyy-MM-dd
. The following example formats
the output of the now
DataWeave function to show supported letters:
%dw 1.0
%output application/json
---
[
{ "dateTime" : now },
{ "era-G" : now as :string { format: "G"} },
{ "year-u" : now as :string {format: "u"} },
{ "year-uu" : now as :string {format: "uu"} },
{ "year-y" : now as :string { format: "y"} },
{ "year-yy" : now as :string { format: "yy"} },
{ "dayOfYear-D" : now as :string { format: "D"} },
{ "monthOfYear-MMMM": now as :string { format: "MMMM"} },
{ "monthOfYear-MMM": now as :string { format: "MMM"} },
{ "monthOfYear-MM": now as :string { format: "MM"} },
{ "monthOfYear-M": now as :string { format: "M"} },
{ "monthOfYear-LL": now as :string { format: "LL"} },
{ "monthOfYear-L": now as :string { format: "L"} },
{ "dayOfMonth-d" : now as :string {format: "d"} },
{ "quarterOfYear-qqq" : now as :string {format: "qqq"} },
{ "quarterOfYear-qq" : now as :string {format: "qq"} },
{ "quarterOfYear-q" : now as :string {format: "q"} },
{ "quarterOfYear-QQQQ" : now as :string {format: "QQQQ"} },
{ "quarterOfYear-QQQ" : now as :string {format: "QQQ"} },
{ "quarterOfYear-QQ" : now as :string {format: "QQ"} },
{ "quarterOfYear-Q" : now as :string {format: "Q"} },
// Understand "Y" and "YY" thoroughly before using it.
{ "weekBasedYear-YY" : now as :string { format: "YY"} },
{ "weekBasedYear-Y" : now as :string { format: "Y"} },
{ "weekInYear-w" : now as :string {format: "w"} },
{ "weekInMonth-W" : now as :string {format: "W"} },
{ "dayOfWeekAbbreviatedName-E" : now as :string {format: "E"} },
{ "dayOfWeekFullName-EEEE" : now as :string {format: "EEEE"} },
{ "localizedDayOfWeek-eeee" : now as :string {format: "eeee"} },
{ "localizedDayOfWeek-eee" : now as :string {format: "eee"} },
{ "localizedDayOfWeek-ee" : now as :string {format: "ee"} },
{ "localizedDayOfWeek-e" : now as :string {format: "e"} },
{ "localizedDayOfWeek-cccc" : now as :string {format: "cccc"} },
{ "localizedDayOfWeek-ccc" : now as :string {format: "ccc"} },
{ "localizedDayOfWeek-c" : now as :string {format: "c"} },
{ "weekOfMonth-F" : now as :string {format: "F"} },
{ "amORpm-a" : now as :string {format: "a"} },
// "h" outputs 12 o'clock as 12. Other hours match "K" output.
{ "hourOfDay1to12-h" : now as :string {format: "h"} },
// "K" outputs 12 o'clock as 0. Other hours match "h" output.
{ "hourOfDay0to11-K" : now as :string {format: "K"} },
{ "clockHourOfAmPm-k" : now as :string {format: "k"} },
{ "hourOfDay0to23-H" : now as :string {format: "H"} },
{ "minuteOfHour-m" : now as :string {format: "m"} },
{ "secondOfMinute-s" : now as :string {format: "s"} },
{ "fractionOfSecond-S" : now as :string {format: "S"} },
{ "millisecondOfDay-A" : now as :string {format: "A"} },
{ "nanosecondCountOfSecond-n" : now as :string {format: "n"} },
{ "nanosecondCountOfDay-N" : now as :string {format: "N"} },
{ "timeZoneID-VV" : now as :string {format: "VV"} },
{ "timeZoneName-zz" : now as :string {format: "zz"} },
{ "localizedZoneOffset-OOOO" : now as :string {format: "OOOO"} },
{ "localizedZoneOffset-O" : now as :string {format: "O"} },
{ "timeZoneOffsetZforZero-XXX" : now as :string {format: "XXX"} },
{ "timeZoneOffsetZforZero-XX" : now as :string {format: "XX"} },
{ "timeZoneOffsetZforZero-X" : now as :string {format: "X"} },
{ "timeZoneOffset-xxx" : now as :string {format: "xxx"} },
{ "timeZoneOffset-xx" : now as :string {format: "xx"} },
{ "timeZoneOffset-x" : now as :string {format: "x"} },
{ "timeZoneOffset-Z" : now as :string {format: "Z"} },
{ "timeZoneOffset-ZZZZ" : now as :string {format: "ZZZZ"} }
]
Notice that the use of the syntax {format: "formattingCharacterOrPattern"}
to format the date or time.
[ { "dateTime": "2019-04-10T14:20:14.271-07:00" }, { "era-G": "AD" }, { "year-u": "2019" }, { "year-uu": "19" }, { "year-y": "2019" }, { "year-yy": "19" }, { "dayOfYear-D": "100" }, { "monthOfYear-MMMM": "April" }, { "monthOfYear-MMM": "Apr" }, { "monthOfYear-MM": "04" }, { "monthOfYear-M": "4" }, { "monthOfYear-LL": "04" }, { "monthOfYear-L": "4" }, { "dayOfMonth-d": "10" }, { "quarterOfYear-qqq": "2" }, { "quarterOfYear-qq": "02" }, { "quarterOfYear-q": "2" }, { "quarterOfYear-QQQQ": "2nd quarter" }, { "quarterOfYear-QQQ": "Q2" }, { "quarterOfYear-QQ": "02" }, { "quarterOfYear-Q": "2" }, { "weekBasedYear-YY": "19" }, { "weekBasedYear-Y": "2019" }, { "weekInYear-w": "15" }, { "weekInMonth-W": "2" }, { "dayOfWeekAbbreviatedName-E": "Wed" }, { "dayOfWeekFullName-EEEE": "Wednesday" }, { "localizedDayOfWeek-eeee": "Wednesday" }, { "localizedDayOfWeek-eee": "Wed" }, { "localizedDayOfWeek-ee": "04" }, { "localizedDayOfWeek-e": "4" }, { "localizedDayOfWeek-cccc": "Wednesday" }, { "localizedDayOfWeek-ccc": "Wed" }, { "localizedDayOfWeek-c": "4" }, { "weekOfMonth-F": "3" }, { "amORpm-a": "PM" }, { "hourOfDay1to12-h": "2" }, { "hourOfDay0to11-K": "2" }, { "clockHourOfAmPm-k": "14" }, { "hourOfDay0to23-H": "14" }, { "minuteOfHour-m": "20" }, { "secondOfMinute-s": "14" }, { "fractionOfSecond-S": "2" }, { "millisecondOfDay-A": "51614271" }, { "nanosecondCountOfSecond-n": "271000000" }, { "nanosecondCountOfDay-N": "51614271000000" }, { "timeZoneID-VV": "America/Los_Angeles" }, { "timeZoneName-zz": "PDT" }, { "localizedZoneOffset-OOOO": "GMT-07:00" }, { "localizedZoneOffset-O": "GMT-7" }, { "timeZoneOffsetZforZero-XXX": "-07:00" }, { "timeZoneOffsetZforZero-XX": "-0700" }, { "timeZoneOffsetZforZero-X": "-07" }, { "timeZoneOffset-xxx": "-07:00" }, { "timeZoneOffset-xx": "-0700" }, { "timeZoneOffset-x": "-07" }, { "timeZoneOffset-Z": "-0700" }, { "timeZoneOffset-ZZZZ": "GMT-07:00" } ]
You can combine the formatting letters to write supported date an time formats into a string, using as in the following way:
%dw 1.0
%output application/json
---
formattedDate: |2003-10-01T23:57:59| as :string {format: "yyyy-MM-dd"}
{
"formattedDate": "2003-10-01"
}
If you are doing multiple similar conversions in your transform, you might want to define a custom type as a directive in the header and set each date as being of that type.
%dw 1.0
%output application/json
%type mydate = :string { format: "yyyy/MM/dd" }
---
{
formattedDate1: |2003-10-01T23:57:59| as :mydate,
formattedDate2: |2015-07-06T08:53:15| as :mydate
}
{
"formattedDate1": "2003/10/01",
"formattedDate2": "2015/07/06"
}
Regular Expression
Type ⇒ ':regex'
Regular Expressions are defined between /. For example /(\d+)/ for represents multiple numerical digits from 0-9. These may be used as arguments in certain operations that act upon strings, like Matches or Replace, or on operations that act upon objects and arrays, such as filters.
Iterators
Type ⇒ ':iterator'
This type is based in the iterator Java class. The iterator contains a collection, and includes methods to iterate through and filter it.
Just like the Java class, the iterator is designed to be consumed only once. For example, if you then pass this value to a logger would result in consuming it and it would no longer be readable to further elements in the flow. |
Custom Types
You can define your own custom types in the header of your transform, then in the body you can define an element as being of that type.
To do so, the directive must be structured as following: %type name = java definition
For example:
%dw 1.0
%type currency = :number { format: "##"}
%type user = :object { class: “my.company.User”}
Usually it’s a good idea to extend an existing type rather than creating one from scratch. For example, above |
To then assign an element as being of the custom type you defined, use the operation as :type
after defining a field:
%dw 1.0
%type currency = :number { format: "##"}
%type user = :object { class: “my.company.User”}
---
customer:payload.user as :user
Defining Types For Type Coercion
Format
The metadata 'format' key is used for formatting numbers and dates.
<items>
<item>
<price>22.30</price>
</item>
<item>
<price>20.31</price>
</item>
</items>
%dw 1.0
%output application/json
%type currency = :number { format: "##"}
---
books: payload.items.*item map
book:
price: $.price as :currency
{
"books": [
{
"book": {
"price": 22.30
}
},
{
"book": {
"price": 20.31
}
}
]
}
In Anypoint Studio, you can define several more values, like separators, quote characters and escape characters. See To Define Input and Output Structure of a Transformation.
Functions and Lambdas
type → :function
In DataWeave, function and lambdas (anonymous functions) are first-class citizen and they can be used inside operators such as a map, mapObject, etc, and can even be assigned to a variable. When using lambdas within the body of a DataWeave file in conjunction with an operator such as map operator, its attributes can either be explicitly named or left anonymous, in which case they can be referenced as $, $$, etc.
Assign to a var
You can define a function as a variable with a constant directive through '%var'
%dw 1.0
%output application/json
%var toUser = (user) -> {firstName: user.givenName, lastName: user.sn}
---
{
"user" : toUser({ givenName : "Annie", sn : "Point" })
}
{
"user": {
"firstName": "Annie",
"lastName": "Point"
}
}
Named attributes with an Operator
This example uses a lambda with an attribute that’s explicitly named as 'name'.
%dw 1.0
%output application/json
---
users: ["john", "peter", "matt"] map ((name) -> upper name)
{
"users": ["JOHN","PETER","MATT"]
}
Anonymous attributes with an Operator
This example uses a lambda with an attribute that’s not explicitly named, and so is referred to by default as '$'.
%dw 1.0
%output application/json
---
users: ["john", "peter", "matt"] map upper $
{
"users": ["JOHN","PETER","MATT"]
}
Declare using function directive
You can declare functions in the Header and these can be invoked at any point in the Body, you can also declare functions anywhere in the body. You refer to them using the form function-name() passing an expression in between the parentheses for each necessary argument. Each expression between the parentheses is evaluated and the result is passed as an argument used in the execution of the function body.
%dw 1.0
%output application/json
%function toUser(user){firstName: user.givenName, lastName: user.sn}
---
{
"user" : toUser({ givenName : "Annie", sn : "Point" })
}
{
"user": {
"firstName": "Annie",
"lastName": "Point"
}
}
Operators Sorted by Type
Below is an index that includes all of the different operators in DataWeave, sorted by the types of the parameters it accepts. Each operator displays what type is accepted on each of its arguments, not all arguments are required.
When you provide an operator with properties that don’t match the expected types, DataWeave automatically attempts to coerce the provided property to the required type. |
Operations Performed on any Type
Operator | Accepted types for each argument |
---|---|
(':any') |
|
(':any', ':type') |
|
(':any', ':array') |
Operations Performed on ':number'
Operator | Accepted types for each argument |
---|---|
(':number', ':number') |
|
(':number', ':number') |
|
(':number', ':number') |
|
(':number', ':number') |
|
(':number') |
|
(':number') |
|
(':number', ':number') |
|
(':number') |
|
(':number') |
|
(':number') |
|
(':number', ':number') |
|
(':number') |
Operations Performed on ':array'
Operator | Accepted types for each argument |
---|---|
(':array') |
|
(':array') |
|
(':array') |
|
(':array') |
|
(':array') |
|
(':array', ':function') |
|
(':array', ':function') |
|
(':array', ':any') |
|
(':array', ':any') |
|
(':array', ':array') |
|
(':array', ':function') |
|
(':array') |
|
(':array', ':function') |
|
(':array', ':any') |
|
(':array', ':function') |
|
(':array', ':string') |
|
(':array', ':array') |
|
(':array', ':function') |
|
(':array', ':array') |
|
(':array') |
Operations Performed on ':string'
Operator | Accepted types for each argument |
---|---|
(':string') |
|
(':string', ':string') |
|
(':string') |
|
(':string') |
|
(':string') |
|
(':string') |
|
(':string') |
|
(':string') |
|
(':string') |
|
(':string') |
|
(':string') |
|
(':string', ':string') |
|
(':string', ':regex') |
|
(':string', ':regex') |
|
(':string', ':string') |
|
(':string', ':regex', ':function') |
|
(':string', ':string') |
|
(':string', ':string') |
|
(':string', ':regex') |
|
(':string', ':regex') |
|
(':string', ':regex') |
|
(':string', ':string') |
|
(':string', ':regex') |
Operations Performed on ':object'
Operator | Accepted types for each argument |
---|---|
(':object') |
|
(':object', ':function') |
|
(':object', ':function') |
|
(':object', ':function') |
|
(':object', ':object') |
|
(':object', ':name') |
|
(':object', ':object') |
|
(':object', ':function') |
Operations Performed on ':datetime'
Operator | Accepted types for each argument |
---|---|
(':datetime', ':timezone') |
|
(':datetime', ':period') |
|
(':datetime', ':period') |
|
(':datetime', ':datetime') |
Operations Performed on ':date'
Operator | Accepted types for each argument |
---|---|
(':date', ':date') |
|
(':date', ':localtime') |
|
(':date', ':time') |
|
(':date', ':timezone') |
|
(':date', ':period') |
|
(':date', ':period') |
Operations Performed on ':time'
Operator | Accepted types for each argument |
---|---|
('#:time', ':time') |
|
('#:time', ':date') |
|
(':time', ':period') |
|
(':time', ':period') |
Type Coercion Table
In DataWeave, types can be coerced from one type to other using the AS Operator. This table shows the possible combinations and the properties from the schema that are used in the transformation.
When you provide an operator with properties that don’t match the expected types, DataWeave automatically attempts to coerce the provided property to the required type. |
Source |
Target |
Property |
:object |
:array |
(1) |
:range |
:array |
|
:number |
:binary |
|
:string |
:binary |
|
:string |
:boolean |
|
:number |
:datetime |
unit |
:localdatetime |
:datetime |
|
:string |
:datetime |
format / locale |
:datetime |
:localdate |
|
:localdatetime |
:localdate |
|
:string |
:localdate |
format / locale |
:datetime |
:localdatetime |
|
:string |
:localdatetime |
format / locale |
:datetime |
:localtime |
|
:localdatetime |
:localtime |
|
:time |
:localtime |
|
:string |
:localtime |
format / locale |
:datetime |
:number |
unit |
:string |
:number |
format / locale |
:array |
:object |
|
:string |
:period |
|
:string |
:regex |
|
:datetime |
:string |
format / locale |
:localdatetime |
:string |
format / locale |
:localtime |
:string |
format / locale |
:localdate |
:string |
format / locale |
:timetype |
:string |
format / locale |
:period |
:string |
|
:timezone |
:string |
|
:number |
:string |
format / locale |
:boolean |
:string |
|
:range |
:string |
(2) |
:type |
:string |
|
:trait |
:string |
|
:datetime |
:time |
|
:localdatetime |
:time |
|
:localtime |
:time |
|
:string |
:time |
format |
:datetime |
:timezone |
|
:time |
:timezone |
|
:string |
:timezone |
(1) Returns and array with all the values of the object. (2) Returns a string with all the values of the range using "," as the separator
Next Steps
-
For a high level overview about the language, see DataWeave Language Introduction
-
For a reference about all of the operators that are available for using, see DataWeave Operators
-
View complete example projects that use DataWeave in the Anypoint Exchange