I just had an epiphany 
Although you can’t use && in a filter to check that multiple attributes are present in a single payload, you can take a different route that I have used several times for other scenarios. Consider the following payload.
{
"identity": {
"id": "ee769173319b41d19ccec6cea52f237b",
"name": "john.doe",
"type": "IDENTITY"
},
"changes": [
{
"attribute": "department",
"oldValue": "sales",
"newValue": "marketing"
},
{
"attribute": "manager",
"oldValue": {
"id": "ee769173319b41d19ccec6c235423237b",
"name": "william.wilson",
"type": "IDENTITY"
},
"newValue": {
"id": "ee769173319b41d19ccec6c235423236c",
"name": "ed.engineer",
"type": "IDENTITY"
}
},
{
"attribute": "email",
"oldValue": "john.doe@hotmail.com",
"newValue": "john.doe@gmail.com"
}
]
}
If you want to only trigger an event when both the “department” and the “manager” have changed, you can use the following JSONpath expression.
$[?($.changes[?(@.attribute == "department")] size 1)][?($.changes[?(@.attribute == "manager")] size 1)]
Update: A simpler expression is $[?($.changes[?(@.attribute == "department" || @.attribute == "manager")] size 2)] .
Let’s break this down.
$[?($.changes[?(@.attribute == "department")] size 1)] will return the entire JSON object IF “department” is an attribute in the changes array. We need the size 1 to ensure that there is exactly one attribute with “department”.
- Since the first part of the expression returns the entire object if “department” is an attribute, then we can apply the same expression, but look for the “manager” attribute:
[?($.changes[?(@.attribute == "manager")] size 1)]. If “manager” exists, then once again it will return the entire object, which is considered a successful JSONpath query.
You can continue to chain together these filter expression to have a virtually infinite list of attributes (or any other value) you want to check exists in the same payload. For example, if you want to check if the attribute email changed OR both the department AND manager changed, you could use this expression:
$[?(($.changes[?(@.attribute == "email")] size 1) || ($.changes[?(@.attribute == "department" || @.attribute == "manager")] size 2))]
The size 2 operation implements the AND (&&) logic by making sure both department and manager are present .