+

DataWeave filter function: How to filter items in an Array

10 min read
Was this tutorial helpful?
Thank you for your feedback!

We would like to thank MuleSoft Ambassador Joshua Erney for their contribution to this developer tutorial.

The filter function was already used as an example for other DataWeave topics like lambdas and generics. However, in this tutorial, you’ll learn some examples or use cases in which you can filter an Array to only contain the items that pass a certain condition. We’ll show you how to write the prefix and infix notations, as well as the use of an explicit lambda and the dollar-sign syntax.

You can try all of these examples with the DataWeave Playground. To learn more about it, check out this tutorial.

Prerequisites

While not required to follow this tutorial, a good understanding of the basic DataWeave concepts would be preferred. You can check out these other tutorials if you feel a bit lost with some concepts:

Syntax

To use filter, you will need to pass two arguments: an Array of any type and a function (or a condition) to filter the data with. The result will be of the same type as the input Array. For example, if you pass an Array of Numbers (Array<Number>), the result will also be an Array of Numbers, but it will contain just the filtered data according to the condition (or the second argument).

filter(Array<T>, ((T,Number) -> Boolean)): Array<T>

Prefix Notation

This function is not commonly used with the prefix notation because of its complexity. But here you can find an example to get the numbers that are more than 1:

Script

1
2
3
4
%dw 2.0
output application/json
---
filter([1, 2, 3], ((num, numIndex) -> num > 1))

Output

1
2
3
4
[
  2,
  3
]

Infix Notation

This is the most used notation for this function because it makes it easier to read and understand.

Script

1
2
3
4
%dw 2.0
output application/json
---
[1, 2, 3] filter ((num, numIndex) -> num > 1)

Output

1
2
3
4
[
  2,
  3
]

When using the infix notation, you don’t have to include all the parameters in the lambda if you’re not using them. However, you do have to include the previous parameters (to the left) whether you’re using them or not. You can only remove the parameters to the right.

In this case, since num is the first parameter, we can also use the following code:

1
2
3
4
%dw 2.0
output application/json
---
[1, 2, 3] filter ((num) -> num > 1)

Dollar-sign Syntax

You don’t always need to include the whole explicit lambda expression as the second argument. You can use the dollar-sign syntax to reference the two arguments that are passed to the lambda (i.e., num and numIndex). In this example, we are filtering all the numbers that are more than 2 and which index is more than 1. $ represents the value of the item (num), while $$ represents the index (numIndex).

Script

1
2
3
4
%dw 2.0
output application/json
---
[1, 2, 3] filter ($ > 2 and $$ > 1)

Output

1
2
3
[
  3
]

The same example with the explicit lambda can be written like this:

[1, 2, 3] filter ((num, numIndex) -> num > 2 and numIndex > 1)

Filter an Array of Strings

Let’s start working with some examples. We’ll start with a simple one: how to filter an Array of Strings (Array<String>) to only include the Strings that contain the word Max.

Script

1
2
3
4
5
6
7
8
%dw 2.0
output application/json
---
[
    "Hello World",
    "Hello Max",
    "Max the Mule"
] filter ($ contains "Max")

Output

1
2
3
4
[
  "Hello Max",
  "Max the Mule"
]

If you’re not familiar with the contains function, it can be used with two Strings to indicate whether the first String contains the second String (or substring). All the different ways to use contains are out of scope for this tutorial, but you can learn more about it in the documentation.

In this example, we used the infix notation and the dollar-sign syntax. We chose to write it this way because the code looks cleaner. If you wanted to use explicit lambda, while still using the infix notation, the same code would look like this:

1
2
3
4
5
6
7
8
%dw 2.0
output application/json
---
[
    "Hello World",
    "Hello Max",
    "Max the Mule"
] filter ((phrase) -> phrase contains "Max")

Filter a Simple Array of Objects

In this example, we have a JSON Array input payload containing objects. Each object has two properties: Name and Age. We will use the filter function to output a new Array of objects (Array<Object>) that only includes the people who are older than 20.

Input payload

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[
  {
    "Name":"Alexandra",
    "Age":80
  },
  {
    "Name":"David",
    "Age":10
  },
  {
    "Name":"Sabrina",
    "Age":21
  }
]

Script

1
2
3
4
%dw 2.0
output application/json
---
payload filter ($.Age > 20)

Output

1
2
3
4
5
6
7
8
9
10
[
  {
    "Name": "Alexandra",
    "Age": 80
  },
  {
    "Name": "Sabrina",
    "Age": 21
  }
]

For this example, we also used the infix notation and the dollar-sign syntax because there is no confusion on what the dollar-sign is referring to since it’s only two fields in each object. Let’s see what would happen if the input payload had more fields and values.

Filter a Complex Array of Objects

In this example, we have a more complex JSON Array input payload containing objects. Each object has three properties: Name, Age, and Phones. The Phones field contains another Array of objects. For our output, we want to only include the people who are older than 20 (as we previously did) and change the Phones field to PrimaryPhones. This new PrimaryPhones field should only include the phones with a Primary field equal to true.

If you’re not familiar with the map function, let’s just say that it’s a way to iterate through the Array. In this case, we need to iterate through the main Array to filter each phone from the Phones Array. How to use map is out of scope for this tutorial, but you can learn more about it in the documentation or this developer tutorial.

Dollar-sign syntax

Let’s first take a look at how this code would look like when we only use the dollar-sign syntax for every single lambda, including two filters and a map.

Input payload

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
[
  {
    "Name":"Alexandra",
    "Age":80,
    "Phones":[
      {
        "Primary":true,
        "Type":"Cellphone",
        "Label":"Personal",
        "Code":"+1",
        "Phone":"123-123-1231"
      },
      {
        "Primary":false,
        "Type":"Cellphone",
        "Label":"Work",
        "Code":"+1",
        "Phone":"123-123-1232"
      },
      {
        "Primary":true,
        "Type":"Cellphone",
        "Label":"Personal",
        "Code":"+1",
        "Phone":"123-123-1233"
      }
    ]
  },
  {
    "Name":"David",
    "Age":10,
    "Phones":[
      {
        "Primary":true,
        "Type":"Cellphone",
        "Label":"Personal",
        "Code":"+1",
        "Phone":"123-123-1233"
      }
    ]
  },
  {
    "Name":"Sabrina",
    "Age":21,
    "Phones":[
      {
        "Primary":false,
        "Type":"Cellphone",
        "Label":"Work",
        "Code":"+1",
        "Phone":"123-123-1234"
      },
      {
        "Primary":true,
        "Type":"Office",
        "Label":"Work",
        "Code":"+1",
        "Phone":"123-123-1235"
      }
    ]
  }
]

Script

1
2
3
4
5
6
7
8
9
10
11
%dw 2.0
output application/json
import update from dw::util::Values
---
payload 
filter ($.Age > 20)
map {
    Name: $.Name,
    Age: $.Age,
    PrimaryPhones: $.Phones filter $.Primary
}

Output

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
[
  {
    "Name": "Alexandra",
    "Age": 80,
    "PrimaryPhones": [
      {
        "Primary": true,
        "Type": "Cellphone",
        "Label": "Personal",
        "Code": "+1",
        "Phone": "123-123-1231"
      },
      {
        "Primary": true,
        "Type": "Cellphone",
        "Label": "Personal",
        "Code": "+1",
        "Phone": "123-123-1233"
      }
    ]
  },
  {
    "Name": "Sabrina",
    "Age": 21,
    "PrimaryPhones": [
      {
        "Primary": true,
        "Type": "Office",
        "Label": "Work",
        "Code": "+1",
        "Phone": "123-123-1235"
      }
    ]
  }
]

As you can see, five different dollar signs are being referenced in this script: one for each filter function ($.Age and $.Primary), and three for the map function ($.Name, $.Age, $.Phones). You can get a bit lost in the code, especially if you’re not very familiar with this syntax or with DataWeave in general.

Explicit lambdas

Let’s now see how this same code would look like when using explicitly declared lambda functions with their parameters, instead of using the dollar-sign syntax.

1
2
3
4
5
6
7
8
9
10
11
12
13
%dw 2.0
output application/json
import update from dw::util::Values
---
payload 
filter ($.Age > 20)
map ((person) -> {
    Name: person.Name,
    Age: person.Age,
    PrimaryPhones: person.Phones filter (
        (phone) -> (phone.Primary)
    )
})

The first filter is still defined with the dollar-sign syntax because it can be understood that it’s referencing the complete payload. But we now defined the person and phone arguments in the map and the second filter. This lets you clarify to which object you’re referring to, instead of just calling all of them with $.

Next Steps

In this tutorial, you learned how to use the filter function with prefix and infix notations, as well as using the dollar-sign or explicit lambdas syntaxes. There is no best practice to use either notation or syntax. It depends on your preference. Some people may find the dollar-sign syntax easier to read, while others will prefer the explicit lambdas. The important thing is that you understand all of them.

Is there an example or use case that you’d like to be showcased in this tutorial? Send us your information and we’ll get in touch with you! Just click on the button below.

Submit a DataWeave Example

Continue your development journey with the rest of the tutorials to become a master in DataWeave.

Try Anypoint Platform for free

Start free trial