# Json

> A column holding a JSON document, edited as raw text in a textarea and validated as JSON.

Source: CBX documentation, version 4.0 preview (unreleased). Canonical page: https://docs.configbox.at/docs/4.0-preview/technical/property-types/json. Last updated 2026-07-27.

---
A column holding a JSON document, edited as raw text in a textarea and **validated as JSON**.

**Storage kind:** `column` · **Column:** `text`

Use it for a JSON column a human may reasonably inspect or edit: a snapshot, a settings bag, an
override map. Two neighbouring choices are often better:

- **Declare no property at all** when the column is engine-owned and an operator has no business
  editing it. `#__cbx_party.custom_fields` deliberately has none — it is LONGTEXT the engine reads
  and writes with hand SQL, and putting a form field on it only creates ways to corrupt it.
- **Use [`rule`](https://docs.configbox.at/docs/4.0-preview/technical/property-types/rule)** when the JSON has a known structure worth editing structurally. `rule`
  stores JSON too, but with a real editor and a schema behind it.

**Never use [`string`](https://docs.configbox.at/docs/4.0-preview/technical/property-types/string) for a JSON column.** The default request handler HTML-escapes the
value, which turns `{"a": "b & c"}` into something that no longer parses, and `check()` validates
nothing — so an operator can save a broken value and only find out when the engine reads it.

## Settings

| Setting | Meaning |
|---|---|
| `rows` | Height of the textarea |

## What it does for you

- **Reads raw.** `getDataFromRequest()` takes the POSTed value without the string mangling, using
  the same path as `ALLOW_RAW`. Backslashes and quotes survive.
- **Normalises.** Valid JSON is re-encoded to a canonical compact form
  (`JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE`), so the stored text does not vary with how the
  operator happened to type it. Invalid input is left **exactly** as typed, so the error message can
  be about what they actually wrote.
- **Validates.** `check()` refuses a non-empty value that does not decode, quoting
  `json_last_error_msg()`. Empty is allowed unless `required`.
- **Pretty-prints in the list.** `getOutputValueFromRecordData()` returns indented JSON, falling
  back to the raw string when it does not decode.

An empty or whitespace-only submission becomes `null`, not `''`.

## What it does not do

There is no schema and no structural editor. The type guarantees the column holds *parseable* JSON,
not JSON of the right *shape*. If the shape matters, validate it in the model's `validateData()` or
in a custom type's `check()` — and consider whether `rule` is the better model.

`text` is 64 KB. A document that can outgrow that needs an explicit `'dataType' => 'longtext'`.

@see rule.md — the counter-example, where a structured editor and a schema do exist
@see string.md — what not to use, and why
@see ../com_configbox_mcp_server.md — how an opaque column is described to an assistant
