JSON Fields New!
Validate and store arbitrary JSON data in a simple CodeMirror (opens new window) editor. The data is automatically deserialized for you and can be
# Settings
JSON fields have no custom settings.
# Development
The JSON field returns an instance of craft\fields\data\JsonData (opens new window), which has a handful of helpful features for interacting with the deserialized data.
Directly outputting the field’s value serializes it back to JSON:
To pretty-print the JSON, you must explicitly call the .getJson()
method:
<pre>
tags are necessary to retain formatting, in the browser. Similarly, the <code>
tag can be used for inline values.
The second argument allows you to customize the indentation:
{# Use tabs instead of the default (two spaces): #}
<pre>{{ entry.myJsonField.getJson(true, '\t') }}</pre>
# Data Types
The data type of the JSON’s root element can be a boolean
, integer
, float
, string
, or array
.
<div class="json {{ data.getType() }}">{{ data }}</div>
The scalar test makes it possible to quickly differentiate simple values from arrays and hashes:
{% if data.getValue() is scalar %}
{# Output directly: #}
{{ data }}
{% else %}
{# This might be more complex, so we’ll print it as nicely as possible: #}
<pre>{{ data.getJson(true) }}</pre>
{% endif %}
Note that we’re directly testing against the field’s underlying deserialized value, not the JsonData
object that wraps it. The latter will always be non-scalar!
# Nested Keys
If you know the structure of a JSON value, you can access nested keys directly from the field:
{{ entry.myJsonField.appId }}
The field only ensures values are valid JSON, but doesn’t enforce any kind of schema. You should always handle input cautiously, to avoid runtime errors:
{{ entry.myJsonField.appId ?? null }}
# Objects + Arrays
JSON “objects” and “arrays” are deserialized into PHP arrays (associative and sequential, respectively), and the JsonData
object provides a means of iterating over them, directly:
<table>
<thead>
<tr>
<th>Key</th>
<th>Value</th>
</tr>
</thead>
<tbody>
{% for key, val in entry.myJsonField %}
<tr>
<td>{{ key }}</td>
<td>
<pre>{{ val is scalar ? val : val|json_encode }}</pre>
</td>
</tr>
{% endfor %}
</tbody>
</table>
Once you have traversed into a data structure, you must explicitly serialize nested objects for output—Craft doesn’t recursively wrap that data with instances of JsonData
!
# GraphQL
JSON fields are treated like plain strings, when queried via GraphQL. Values must be deserialized in the client or app:
const gql = `
query MyQuery {
globalSet(handle: "siteOptions") {
... on siteOptions_GlobalSet {
analyticsConfig
}
}
}
`;
fetch('/api', {
body: gql,
method: 'POST',
headers: {
'Content-Type': 'application/graphql',
'X-Craft-Gql-Schema': '*',
},
})
.then(response => response.json())
.then(json => JSON.parse(json.data.globalSet.analyticsConfig))
.then(config => new AcmeAnalytics(config));