Skip to content

[5.x]: JsonData: null coalescing (??) behaves differently with dot vs bracket access in Twig #18656

@samhibberd

Description

@samhibberd

What happened?

Description

When accessing non-existent keys on a craft\fields\data\JsonData object in Twig, the null coalescing operator (??) behaves inconsistently depending on whether you use dot notation or bracket notation. Dot access throws an exception instead of allowing ?? to fall through to the fallback value.

Docs look to suggest this should be possible:

The field ensures values are valid JSON, but does not enforce any kind of schema. You should always handle input cautiously, to avoid runtime errors: {{ entry.myJsonField.appId ?? null }}

https://craftcms.com/docs/5.x/reference/field-types/json.html#nested-keys

Steps to reproduce

  1. Create a JSON field (e.g. data) on an entry
  2. Set the field value to a simple object, e.g. {"title": "Hello"}
  3. In a Twig template, access a key that does not exist using both access styles:
{# Bracket access — works as expected, returns 'fallback' #}
{{ entry.data['nonExistent'] ?? 'fallback' }}

{# Dot access — throws an exception instead of returning 'fallback' #}
{{ entry.data.nonExistent ?? 'fallback' }}

Expected behaviour

Both expressions should behave identically and return 'fallback' when the key does not exist on the JsonData object.

Actual behaviour

Bracket access correctly falls through to the fallback value.

Dot access throws:

Calling unknown method: craft\fields\data\JsonData::nonExistent()

It appears that Twig's dot-access resolution on the JsonData object is falling through property checks and reaching Yii's __call() magic method, which throws before ?? has a chance to handle the missing key.

Additional context

This also means that the | default() filter doesn't work reliably with dot access either:

{{ entry.data.nonExistent | default('fallback') }}

The workaround is to always use bracket notation when accessing JsonData keys, but this is unintuitive — dot and bracket access behave identically on plain arrays and most other objects in Twig.

Since JsonData extends yii\base\BaseObject (which provides __get(), __isset(), and __call() implementations that throw on unknown properties/methods), the fix likely involves overriding one or more of these to delegate to ArrayAccess for key lookups, so that Twig's attribute resolution can handle missing keys gracefully.

Craft CMS version

5.8.23

PHP version

8.2+

Operating system and version

No response

Database type and version

No response

Image driver and version

No response

Installed plugins and versions

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions