> ## Documentation Index
> Fetch the complete documentation index at: https://ngquct-docs-partner-confirmed.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Cell and Row Viewers

> View and edit JSON, PHP serialized, image and binary cell values, set per-column display formats, and inspect whole rows in the sidebar

Click the chevron on a JSON or blob cell to open its value in a popover anchored to that cell. Which viewer opens follows the column: its declared type, or the **Display As** choice on its header, and that choice changes rendering only, never what is stored.

Whether it opens for editing follows the row and the column. A row marked for deletion opens nothing at all. A result the app cannot write back to, a generated column, and a column the driver marks immutable such as MongoDB's `_id` all open read-only; [Change Tracking](/features/change-tracking) covers which results are writable. PHP serialized values, and binary past the hex cap, are read-only for everyone.

## Display as formats

Right-click a column header and pick **Display As**. The submenu lists the formats that fit the column type, with a checkmark on the active one.

| Format | Column types | Effect |
| - | - | - |
| Raw Value | all | Shows the stored value, and turns off detection for that column |
| Text | binary | Reads the bytes as UTF-8, trailing `BINARY(N)` padding trimmed |
| UUID | binary, text | Renders 16 raw bytes or a 32-digit hex string as a hyphenated UUID |
| Unix Timestamp (seconds) | integer | Renders the number as a formatted date |
| Unix Timestamp (milliseconds) | integer | Same, treating the number as milliseconds |
| JSON | text | Opens the cell in the JSON viewer |
| PHP Serialized | text | Opens the cell in the PHP serialized viewer |

An override persists per column, scoped to the connection and table. A column with a format set copies in that format when you copy the single cell; a block of cells or a whole row always copies the stored value.

Id-like binary and character columns, integer columns whose names read as timestamps, and binary columns whose first rows all read as UTF-8 pick up their format on their own. **Smart value detection** in [Settings > Data](/customization/data-settings) turns that off, and a manual choice always wins over it, **Raw Value** included. MongoDB binary columns never offer UUID, since the driver decodes them under its own Legacy UUID Encoding setting; see [MongoDB](/databases/mongodb).

**Text** decides per cell, not per column: an image or a hash sitting in a column set to **Text** still reads as `0x89504E…`. The cell edits as hex either way.

## JSON viewer

A JSON-typed column opens on the chevron; double-click or `Enter` edits it inline instead. A text column holding JSON needs **Display As > JSON** first.

The popover has two modes. **Text** is syntax-highlighted and pretty-printed, and editable when the cell is. **Tree** is a collapsible outline with a search field. It never edits, but its rows and the text in them select and copy. Both keep your key order and exact number values, integers larger than JavaScript can represent included.

<Frame caption="JSON editor popover with Text and Tree modes">
  <img className="block dark:hidden" src="https://mintcdn.com/ngquct-docs-partner-confirmed/VHT5rmphj4o5J8oC/images/json-editor-popover.png?fit=max&auto=format&n=VHT5rmphj4o5J8oC&q=85&s=255ca6e42f293588d1dcdafe4f10f0c2" alt="JSON editor popover" width="3024" height="1722" data-path="images/json-editor-popover.png" />

  <img className="hidden dark:block" src="https://mintcdn.com/ngquct-docs-partner-confirmed/VHT5rmphj4o5J8oC/images/json-editor-popover-dark.png?fit=max&auto=format&n=VHT5rmphj4o5J8oC&q=85&s=c588905ce8519b0599f7fa95b42484d8" alt="JSON editor popover" width="3024" height="1722" data-path="images/json-editor-popover-dark.png" />
</Frame>

The mode you switch to becomes the default for the next value, which is the same preference as **JSON Viewer > Default view** in Settings. The pop-out button detaches the viewer into its own resizable window.

Opening a value and seeing it pretty-printed is not an edit: the row is marked changed only once you alter the content. **Save** commits a compact value, key order and numbers preserved, through the [change tracking](/features/change-tracking) queue. Text that is not valid JSON prompts first.

A NULL or empty cell reads **Empty Value** in **Tree** mode. On an editable cell, switch to **Text** to enter JSON.

### Selecting and copying in a tree

Click a row to select it. The arrow keys move the selection, `Shift` and `Cmd` extend it, and `Cmd+A` selects every row. `Cmd+C` copies the selected values, one per line: a string without its quotes, an object or array as compact JSON. A row inside a selected object or array is already part of that JSON and is not copied a second time.

For part of a value, select its row, drag across the text or double-click a word, then press `Cmd+C`. Text copies as the row shows it: a long string shortened, a line break written as `\n`. **Copy Value** on the right-click menu copies the whole value.

**Copy Key** and **Copy Key Path** sit on the same menu. A path reads `$.user.emails[0]`. A key that is not a plain identifier is quoted, as in `$."content-type"`, the form SQLite, PostgreSQL, MariaDB and DuckDB read in a JSON path.

`Escape` ends a text selection first, then clears the row selection. Pressed once more, it closes the popover and drops an edit you have not saved.

### Links and color swatches

A string that is one whole `http`, `https` or `mailto` address is drawn as a link. The first click selects its row. Click the link in a selected row and it opens in your browser or mail app. `Space` opens the link of a single selected row, the right-click menu has **Open Link** and **Copy Link**, and holding the pointer over the link shows the address in full.

Everything else stays text: `file:` and every other scheme, `www.example.com` with no scheme, an address inside a longer string or with a space beside it, an address carrying a user name and password, a `mailto:` with anything after the address, and an address too long for its row that is cut off before the end of its host name, since the part shown could name another site. **Copy Value** still copies that address whole. An address has to be plain ASCII with the rest percent-escaped, so `/wiki/Vi%E1%BB%87t_Nam` links and `/wiki/Việt_Nam` does not.

A string that is a CSS color carries a swatch of that color beside it.

| Format | Examples |
| - | - |
| Hex, 3, 6 or 8 digits | `#f80`, `#ff8800`, `#ff880080` |
| `rgb()` and `rgba()` | `rgb(255, 136, 0)`, `rgb(255 136 0 / 50%)` |
| `hsl()` and `hsla()` | `hsl(32, 100%, 50%)`, `hsl(32deg 100% 50% / 0.5)` |

Any 3, 6 or 8 hex digits after `#` count, so an order number stored as `#404` gets a swatch too. Four-digit hex such as `#f80c` and color names such as `orange` get none.

### Filtering a tree

The search field above the tree filters keys and values as you type. The [PHP serialized tree](#php-serialized-viewer) works the same way.

* Matching ignores case and accents, so `cafe` finds `café`. Full-width and half-width differ: `ABC` does not find `ＡＢＣ`.
* A row matches on its whole value, not the shortened form shown, so a match deep inside a long string counts. A match under a collapsed parent opens its parents, and a key that matches keeps its contents and stays expandable.
* Only text from the document matches. A JSON array position such as `[1]`, a count such as `{2 keys}` and the `…` row are the tree's own labels, and no filter finds them.
* A filter that matches nothing says so, and says separately when the document was cut at 5,000 nodes, since the rows past the cut were never searched.

### Arrays of JSON

A PostgreSQL `jsonb[]` or `json[]` cell opens on its elements: the list at the top, the selected element in the same Text and Tree viewer below.

Add, remove and reorder elements with the controls under the list. **NULL** on an element writes a SQL NULL, which is a different value from the JSON `null` an element can hold: the list shows the first as `NULL` and the second as `null`. **Edit as Text** switches to the raw `{…}` literal.

Reading an element does not change it. Only an element whose JSON you alter is rewritten, and it is written back compact, so a `json[]` column keeps the exact text it stored for every element you left alone.

## PHP serialized viewer

Set **Display As > PHP Serialized** on a text column, then double-click or press `Enter`. The viewer is read-only: PHP serialized values round-trip through PHP itself.

**Tree** mode is the JSON tree with PHP's types: it filters, [selects, copies](#selecting-and-copying-in-a-tree) and draws [links and color swatches](#links-and-color-swatches) the same way, with type badges on the nodes (`str`, `int`, `arr`, `obj`, `ser`, `ref`) and visibility badges on object members (`protected`, `private (ClassName)`). A custom-serialized class (the `C:` token) is one opaque leaf that copies as its whole payload, and a reference (`r:`/`R:`) shows as `→ #N` and is not followed. **Raw** mode shows the original string with text selection.

An array or object row copies as its summary, such as `[2 items]`, not as its contents, so each row you select inside it copies its own value after the summary. Copy the serialized text from **Raw** mode instead.

## Blob and hex

A blob cell renders in the grid as compact hex (`0x48656C…`), unless its column reads as text. Click the chevron or double-click for the popover: a classic hex dump with offset, byte columns, and ASCII, plus an editable hex field under it on an editable table. That field takes spaced or continuous hex, with or without a `0x` prefix, and invalid hex disables **Save**.

Bytes that read as an image open on the picture instead, with **Hex** the second segment. The [image viewer](#image-viewer) covers that.

## Image viewer

A cell whose content is an image opens on the drawing, with its stored form one segment away: **Hex** for a binary column, **Source** for SVG markup in a text column. The source stays editable wherever the cell is, and **Save** commits it through the same [change tracking](/features/change-tracking) queue as any other edit.

Detection reads the value, not the column, since the same PNG turns up in `BLOB`, `BYTEA` and `VARBINARY`, and SVG arrives as often in a text column as a binary one. PNG, JPEG, JPEG 2000, GIF, TIFF, BMP, ICO, WebP, HEIC, HEIF and AVIF are identified from their header; SVG from its root element, behind any byte order mark, XML declaration, comment or doctype. A PDF, a Photoshop file and a camera raw file are left as hex, since a database client that opened them as "the image in this cell" would be guessing. **Display As > Raw Value** on the column turns detection off.

<Frame caption="One value, drawn in the popover and again in the row inspector">
  <img className="block dark:hidden" src="https://mintcdn.com/ngquct-docs-partner-confirmed/w-T80b4v-_ApVfgU/images/cell-image-viewer.png?fit=max&auto=format&n=w-T80b4v-_ApVfgU&q=85&s=c482bf6e6147b014cd4720ab54160fc2" alt="A cell popover and the row inspector each drawing an SVG logo on a transparency checkerboard, both showing Image and Source segments" width="1512" height="861" data-path="images/cell-image-viewer.png" />

  <img className="hidden dark:block" src="https://mintcdn.com/ngquct-docs-partner-confirmed/w-T80b4v-_ApVfgU/images/cell-image-viewer-dark.png?fit=max&auto=format&n=w-T80b4v-_ApVfgU&q=85&s=c4aec4634f90bb49c7272ad478b0cd55" alt="A cell popover and the row inspector each drawing an SVG logo on a transparency checkerboard, both showing Image and Source segments" width="1512" height="861" data-path="images/cell-image-viewer-dark.png" />
</Frame>

Transparency draws on a checkerboard. The footer names the format and, for a raster image, the stored pixel size, which is what the file holds rather than what fits the pane. **Copy Image** puts the drawing on the clipboard as an image; **Copy** on the cell itself still copies the stored value. The pop-out button opens a resizable window, read-only there.

SVG rasterizes in a separate process that reads the markup and nothing else. It reaches no network and no file: an `<image href="https://…">`, an `@import`, an external entity and a `<script>` all draw as nothing. A document that cannot be drawn within three seconds is abandoned and the pane says so.

## Limits

A value that refuses to open in one mode still opens in another.

| Viewer | Cap | Past the cap |
| - | - | - |
| JSON pretty-printing | 500,000 characters | The value shows as stored |
| JSON tree | 100,000 characters, indentation not counted | "JSON Too Large". Read it in Text mode |
| JSON and PHP trees | 5,000 nodes | The first 5,000 load, and a `…` row marks the cut |
| PHP serialized | 5,000,000 characters, 256 levels deep | Tree shows a placeholder, Raw still works |
| Hex dump and hex editor | 10 KB | The dump is truncated, and the editor opens read-only |
| Blob cell in the grid | First 64 bytes | Rendered as `0x48656C…` |
| Image preview | 16 MB | "Too Large to Preview". The source still opens |
| SVG rasterizing | 3 seconds | "Could Not Render This Image". The markup still opens |
| Geometry map | 100,000 shapes or 2,000,000 points in one value | "This geometry has more points than the map draws." **Text** still opens |

## Row details inspector

**View > Show Inspector** (`Cmd+Option+I`), or the toolbar button at the trailing end, opens it. The table and which row of how many is selected sit under the [pane's header](/features/connection-window#the-trailing-pane), then the fields. Each field carries its column name and type on one line, with the value on the line beneath, so the value gets the row's full width however long the column name is. A field's editor follows its content, with no **Display As** step, and the first match wins.

| Content | Editor |
| - | - |
| A spatial column whose value the map reads, or GeoJSON in a JSON column | [Map](#geometry-fields), stored value behind **Text** |
| A JSON column, or text that parses as JSON | JSON editor |
| A PHP serialized value | Read-only [PHP viewer](#php-serialized-viewer) |
| An image, in any column | [Image viewer](#image-viewer), source behind the second segment |
| An enum, set, or boolean column | Picker |
| A blob column, or other bytes in a spatial column | Hex editor |
| A `TEXT` variant, `CLOB` or `NTEXT` column, or any value with a line break or over 80 characters | Scrolling text box |
| Anything else | Single-line field |

<Frame caption="Row details inspector with per-field editors">
  <img className="block dark:hidden" src="https://mintcdn.com/ngquct-docs-partner-confirmed/hTOmSsx6uRz_zO-y/images/row-details-inspector.png?fit=max&auto=format&n=hTOmSsx6uRz_zO-y&q=85&s=0eab44bd154a0d187a37b7c6b9ea4199" alt="Row details inspector" width="1560" height="960" data-path="images/row-details-inspector.png" />

  <img className="hidden dark:block" src="https://mintcdn.com/ngquct-docs-partner-confirmed/hTOmSsx6uRz_zO-y/images/row-details-inspector-dark.png?fit=max&auto=format&n=hTOmSsx6uRz_zO-y&q=85&s=65c3a7cf03e0069731c4289fab856f87" alt="Row details inspector" width="1560" height="960" data-path="images/row-details-inspector-dark.png" />
</Frame>

Type in a field and the grid cell beside it follows, tinted as a pending change like an inline edit, and saved with the rest of them on `Cmd+S`. The length test reads the stored value, so a long value pasted into a single-line field stays on one line until you save and reselect the row.

The hex editor shows the first 10 KB of a blob. Past that it reads **Truncated, read only** and refuses edits, rather than saving back the part it could show.

The text box, the JSON editor and the map each carry a drag handle under them, with separate remembered heights that survive a relaunch.

**Open in Window** detaches a JSON, PHP or text value into its own resizable window; on an editable row, edits there join the same pending changes as the field. An image and a map detach read-only. The expand button on a JSON, PHP, long text or geometry field grows it to fill the inspector's height with the other fields still listed around it; click it again to shrink it back. Binary and image fields draw at a fixed height and carry no expand button, and neither does a geometry field stored as bytes, whose map still takes the drag handle.

Every field carries a menu at its trailing edge, and right-clicking the field opens the same one. **Set NULL**, **Set DEFAULT**, **Set EMPTY** and **SQL Functions** need an editable field; `Ctrl+Option+N` and `Ctrl+Option+D` reach the first two from the keyboard. **Copy Value** is always there, and a read-only field keeps its text selectable.

With no row selected, the inspector describes the table the tab is bound to: data, index and total size, row count, average row size, engine, collation, and creation and update dates, as far as the database reports them. A tab with no table of its own, such as a query, leaves it empty. On a Structure tab it follows the structure grid and names the selected column.

### Geometry fields

Select a row with a spatial column and its field opens on a map of that one value: a marker for a point, the path of a line, a polygon with its holes, and every member of a multi-part value or a collection. GeoJSON in a JSON column gets the same field.

**Text**, the other segment, holds the stored value in the editor it would otherwise have: the text box for WKT, the JSON editor for GeoJSON, the hex editor for WKB bytes. Edit it there and **Map** draws the edited value before any save. Typing never switches the segment. The segment picked last is the one the next geometry field opens on, remembered on this Mac.

Drag the map to pan it; pinch, double-click or Cmd + scroll to zoom. A plain scroll moves the inspector. **Fit to Geometry** frames the value again, and **Open in Window** on the **Map** segment opens the map alone in a resizable window.

The caption under the map names the geometry type and its SRID, adds the latitude and longitude of a single point, and counts any parts left out because the map could not place them.

A value with nothing to draw opens on **Text**, and **Map** says why in a sentence: NULL, an empty geometry, an SRID the map does not place, a curve type, coordinates out of range for their SRID, a shape wholly past 85 degrees of latitude, or several selected rows that hold different values. [Map mode](/features/data-grid#map-mode) lists the formats and SRIDs the map reads. A value in none of those formats keeps the editor it had, with no **Map** segment: a text editor for text, the hex editor for bytes.

## Row as JSON

Right-click a row and choose **Show Row as JSON**, or open the inspector and pick **JSON** from the ellipsis menu at the trailing end of the pane's header. The row prints as one JSON object, keys in the result's own column order: numbers and booleans unquoted, NULL as `null`, binary as hex. Like **Fields** beside it, it prints every column the result carries, including any hidden in the grid. A JSON column, and a text column holding a document, arrive as nested keys instead of as a string.

The pair is offered for a data-grid row and for nothing else. A Structure tab's column definition has no JSON form, and neither does the table information the inspector shows with no row selected, so the choice is not in the menu there.

<Frame caption="A Track row as JSON, with its AlbumId key opened onto the Album row">
  <img className="block dark:hidden" src="https://mintcdn.com/ngquct-docs-partner-confirmed/hTOmSsx6uRz_zO-y/images/row-as-json.png?fit=max&auto=format&n=hTOmSsx6uRz_zO-y&q=85&s=14273044cedb76dace447b7bb0a40524" alt="Row as JSON" width="1512" height="861" data-path="images/row-as-json.png" />

  <img className="hidden dark:block" src="https://mintcdn.com/ngquct-docs-partner-confirmed/hTOmSsx6uRz_zO-y/images/row-as-json-dark.png?fit=max&auto=format&n=hTOmSsx6uRz_zO-y&q=85&s=5ab6e17401d6153a671e1bb8a1c2e78b" alt="Row as JSON" width="1512" height="861" data-path="images/row-as-json-dark.png" />
</Frame>

A foreign key carries a disclosure control. Click it and the referenced row is fetched and printed underneath; a foreign key inside that row expands the same way, five levels down. A key pointing back at a row already open in the tree, and one past the fifth level, carry a warning icon that says which. A NULL foreign key has no control.

**Always Expand Foreign Keys**, in the same header menu, fetches the first level on every row selected from then on. It starts off and stays off until you turn it on, every session, since each key it follows is a query. **Copy Visible** puts the printed lines on the pasteboard as they stand, and **Collapse All** and **Expand All** sit beside it. All four appear only while the JSON rendering is on screen. Long text wraps rather than being cut.

The filter field takes text, or a regular expression wrapped in slashes such as `/^rental/`. It matches keys and values, keeps the keys that lead to a match along with everything under a key that matches, and opens what was collapsed. `Escape` clears it. An invalid expression outlines the field in red and filters nothing.

Under a filter, the disclosure controls close and reopen what the filter kept. A foreign key that matches only by its value has no control until you clear the filter.

A string value carries the same [links and color swatches](#links-and-color-swatches) as the tree. A line here has no selection, so a link opens on the first click.

Editing stays on **Fields**. Right-click the empty part of a line, before its text or past its end, for **Copy Value** and **Copy Key**; a link adds **Open Link** and **Copy Link**, and a foreign key line adds **Open** for the referenced table, filtered to that row. A right-click on the text itself shows the text menu instead.

Caps: a document stored as more than 100,000 characters prints as a string rather than as nested keys. The [JSON tree](#limits) has the same cap, counted without indentation. A binary value shows its first 64 bytes followed by an ellipsis, the same cap the grid's own **Copy** applies.

For whole-row JSON, switch the result to JSON mode with the switcher at the leading edge of the status bar, or from **View > Result View**. It shows what the [grid](/features/data-grid) shows, in the same order, minus hidden columns and rows marked for deletion, which the count line reports separately. Select rows in Data mode first to narrow it, then click **Copy JSON**. Its **Tree** mode is the cell viewer's tree, where `Cmd+A` then `Cmd+C` copies one row object per line.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.