Contact Us 1-800-596-4880

Pattern Matching in DataWeave Through match Statements

DataWeave 2.2 is compatible and bundled with Mule 4.2. This version of Mule reached its End of Life on May 2, 2023, when Extended Support ended.

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. Before you begin, note that DataWeave version 2 is for Mule 4 apps. For a Mule 3 app, refer to the DataWeave 1.0 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.

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 a 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 or literalMatch), while the else statement can refer to the input expression using the default parameter name $, an unnamed parameter.

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
%dw 2.0
output application/json
---
"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 myInput.string and returns a boolean. The second field performs the same match, but it returns an object that contains both a boolean and a reference to the validated value.

DataWeave Script
%dw 2.0
var myInput = {
  "string": "Emiliano"
}
output application/json
---
{
  a: myInput.string match {
    case "Emiliano" -> true
    case "Mariano" -> false
  },
  b: myInput.string match {
    case str: "Emiliano" -> { "matches": true, value: str }
    case str: "Mariano" -> { "matches": false, value: str }
  }
}
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 myInput.string against two alternatives and conditionally appends a different string to it. The second field evaluates if the value in myInput.number is greater than (>), less than (<), or equal to (==) 3 and returns the corresponding string.

DataWeave Script
%dw 2.0
var myInput = {
  "string": "Emiliano",
  "number": 3.14
}
output application/json
---
{
  a: myInput.string match {
    case str if str == "Mariano" -> str ++ " de Achaval"
    case str if str == "Emiliano" -> str ++ " Lesende"
  },
  b: myInput.number match {
    case num if num == 3 -> "equal"
    case num if num > 3 -> "greater than"
    case num if num < 3 -> "less than"
  }
}
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 data type of myInput.a and returns a string with the corresponding type name. The second field is similar but also returns the value of the myInput.b.

DataWeave Script
%dw 2.0
var myInput =
{
  "a": "Emiliano",
  "b": 3.14
}
output application/json
---
{
  a: myInput.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: myInput.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' : myInput.b} }
  }
}
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 variable (myInput) 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.

DataWeave Script
%dw 2.0
var myInput = {
  "phones": [
    "+1 (415) 229-2009",
    "(647) 456-7008"
  ]
}
output application/json
---
{
  a: myInput.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: myInput.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] }
 })
}
Output
{
  "a": [
    {
      "country": "1"
    },
    {
      "area": "647",
      "number": "456-7008"
    }
  ],
  "b": [
    {
      "country": "1",
      "area": "415",
      "number": "229-2009"
    },
    {
      "area": "647",
      "number": "456-7008"
    }
  ]
}