What you will do
You will run the prepared expression in the playground above, change one input at a time, and explain the result. Start in CEL only, then repeat the same rule in CEL + JSON.
How it works
Presence and value are different questions. has(user.email) checks whether the selected member exists without reading it first. If it is absent, the conditional operator chooses the fallback. A present member whose value is null is still present.
Read the prepared example
The CEL + JSON rule is:
has(user.email) ? user.email : 'not provided'Its input is:
{
"user": {
"name": "Maya"
}
}The CEL only tab contains the values and the rule in one expression. The enabled cel.bind() extension keeps each name local to its final argument.
Evaluation step by step
- The
usermap has noemailkey. has(user.email)returnsfalse.- The conditional expression returns
"not provided".
Your task
- Run the initial example.
- Add
"email": "maya@example.test"to the map or JSON. - Then set the email value to
nulland observe that presence alone does not guarantee a string.
Expected observation: An added email is returned; a present null value may require an additional value check.
Common mistake
Writing user.email != null reads the member before it proves that the member exists. Use has() when presence is uncertain.
Show the explanation
No. It only tells you that the member is present.
Knowledge check
Does has(user.email) tell you that the email is non-empty text?
Key takeaway
Check presence before access, then validate the value separately when its content matters.
Sources
CEL-DEV— official CEL overview.CEL-LANG— official CEL language definition.CEL-GO-BIND— official documentation for the optionalcel.bind()extension used by the self-contained tab.