Pattern Matching in DataWeave Through match Statements

DataWeave 2.1 is compatible with Mule 4.1. Standard Support for Mule 4.1 ended on November 2, 2020, and this version of Mule will reach its End of Life on November 2, 2022, when Extended Support ends.

Deployments of new applications to CloudHub that use this version of Mule are no longer allowed. Only in-place updates to applications are permitted.

MuleSoft recommends that you upgrade to the latest version of Mule 4 that is in Standard Support so that your applications run with the latest fixes and security enhancements.

The match statement behaves like a match or switch statement in other languages, like Java or C++, and routes an input expression to a particular output expression based on some conditions.

Match Statement Syntax:
inputExpression match {
  case <condition> -> <routing expression>
  case <condition> -> <routing expression>
  else -> <default routing expression>
}

As in other languages, the DataWeave match statement provides compact way to organize multiple, chained if-else statements. A match expression consists of a list of case statements that optionally end with an else statement. Each case statement consists of a conditional selector expression that must evaluate to true or false. This conditional expression corresponds to the condition expressed by an if statement, followed by a corresponding DataWeave routing expression that can include the match statement’s input expression.

Each case statement can be an if statement, or the case statement can use other pattern-matching shortcuts to define the case statement’s condition. If a case statement is false, its routing expression is ignored.

DataWeave supports four different types of patterns for a case statement’s condition:

Each case can be named or unnamed. If the case is named, the name stores the input expression as a local variable that can be used both in that case statement’s conditional expression and in the corresponding routing expression.

Match Statement Structure
value match {
  case (<name>:) <condition> -> <routing expression>
  case (<name>:) <condition> -> <routing expression>
  else -> <when none of them matched>
}

As this example shows, the expression returns the results of the first matching case statement:

Match Statement Example
%dw 2.0
output application/json
---
"hello world" match {
	case word matches /(hello)\s\w+/ ->  word[1] as String ++ " was matched"
	case literalMatch: "hello world" -> upper(literalMatch)
	case hasOne if( hasOne is Object and hasOne.three? ) -> hasOne.three
	else -> $
}
Output
"hello was matched"

Notice that you can refer to the input expression ("hello world") through each case statement’s local variable name (that is, word, literalMatch, or hasOne), while the else statement can refer to the input expression using the default parameter name $, an unnamed parameter.

If you want to name the input expression in the else statement, you can replace the else statement with a case statement that is always true:

Match Statement Example
"hello world" match {
	case word matches  /(hello)\s\w+/ ->  word[1] ++ " was matched"
	case literalMatch: "hello world" -> upper(literalMatch)
	case last if(true) -> last
}

For use cases in which the input is of type String, you can also use the match function in the dw::Core module to test the string against a regex pattern. The function returns an array with the strings that match the entire regex and any capture groups.

For use cases that require a Boolean result based on whether a string matches a regex pattern, you can use the matches function in the dw::Core module instead of using pattern matching or the module’s match function.

Pattern Matching to Literal Values

Matches when the evaluated value equals a simple literal value.

In this example, the first field 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.

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

Pattern Matching on Expressions

Matches when a given expression returns true.

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 "greater", "less than", or "equal" to 3 and returns the corresponding string.

Transform
%dw 2.0
output application/json
---
{
  a: payload.string match {
    case str if str == "Mariano" -> str ++ " de Achaval"
    case str if str == "Emiliano" -> str ++ " Lesende"
  },
  b: payload.number match {
    case num if num == 3 -> "equal"
    case num if num > 3 -> "greater than"
    case num if num < 3 -> "less than"
  }
}
Input
{
  "string": "Emiliano",
  "number": 3.14
}
Output
[
  {
    "a": "Emiliano Lesende",
    "b": "greater than"
  }
]

Pattern Matching on the Data Type

Matches when the evaluated value is the specified data type.

In this example, the first field evaluates the type of payload.a and returns a string with the corresponding type name. The second field is similar but also returns the value of the payload.b.

Transform
%dw 2.0
output application/json
---
{
  a: payload.a match {
    case is Object -> 'OBJECT'
    case is String -> 'STRING'
    case is Number -> 'NUMBER'
    case is Boolean -> 'BOOLEAN'
    case is Array -> 'ARRAY'
    case is Null -> 'NULL'
    else -> 'ANOTHER TYPE'
  },
  b: payload.b match {
    case y is Object -> { 'Type': { 'OBJECT' : y} }
    case y is String -> { 'Type': { 'STRING' : y} }
    case y is Number -> { 'Type': { 'NUMBER' : y} }
    case y is Boolean -> { 'Type': { 'BOOLEAN' : y} }
    case y is Array -> { 'Type': { 'ARRAY' : y} }
    case y is Null -> { 'Type': { 'NULL' : y} }
    else -> { 'Type': { 'ANOTHER TYPE' : payload.b} }
  }
}
Input
{
  "a": "Emiliano",
  "b": 3.14
}
Output
{
  "a": "STRING",
  "b": {
    "Type": {
      "NUMBER": 3.14
    }
  }
}

Pattern Matching on Regular Expressions

Matches when the evaluated value fits a given regular expression (regex), specifically a regex "flavor" supported by Java. In this example, the input payload includes an array of strings. The script uses the map function to iterate through the array. It evaluates each element against a Java regex and outputs an object based on matches to the input.

Transform
%dw 2.0
output application/json
---
{
  a: payload.phones map ($ match {
     case phone matches /\+(\d+)\s\((\d+)\)\s(\d+\-\d+)/ -> { country: phone[1]}
     case phone matches /\((\d+)\)\s(\d+\-\d+)/ -> { area: phone[1], number: phone[2] }
   }),
 b: payload.phones map ($ match {
   case phone matches /\+(\d+)\s\((\d+)\)\s(\d+\-\d+)/ -> { country: phone[1], area: phone[2], number: phone[3] }
   case phone matches /\((\d+)\)\s(\d+\-\d+)/ -> { area: phone[1], number: phone[2] }
 })
}
Input
{
  "phones": [
    "+1 (415) 229-2009",
    "(647) 456-7008"
  ]
}
Output
{
  "a": [
    {
      "country": "1"
    },
    {
      "area": "647",
      "number": "456-7008"
    }
  ],
  "b": [
    {
      "country": "1",
      "area": "415",
      "number": "229-2009"
    },
    {
      "area": "647",
      "number": "456-7008"
    }
  ]
}

Was this article helpful?

💙 Thanks for your feedback!

Edit on GitHub