Filament JSON

Filament plugin for processing JSON field
Version

Beautiful JSON viewer column for Filament v5 tables.

  • Render modes: Tree / Table
  • Presentation modes: Inline / Modal / Drawer
  • Inline shows pretty-printed raw JSON (compact, fast) with click-to-copy
  • Modal/Drawer support Expand all / Collapse all (Tree mode) and Copy JSON
  • Raw JSON strings are decoded when valid; invalid strings are displayed as scalar values.
  • Valid falsy JSON values (false, 0, "0", empty strings) are preserved.
  • Polished light/dark styling. No build steps required for your app.

Installation

composer r pepperfm/filament-json:^5.0

Previous major versions:

  • Filament 4 → composer r pepperfm/filament-json:^4.0 or ^3.0
  • Filament 3 → composer r pepperfm/filament-json:^2.0

Optionally publish config or views if you want to customize them:

php artisan vendor:publish --tag="filament-json-config"
php artisan vendor:publish --tag="filament-json-views"

No Tailwind/Vite setup is required — the package ships a compiled stylesheet and registers it via Filament assets.


Quick start

use PepperFM\FilamentJson\Columns\JsonColumn;
use PepperFM\FilamentJson\Enums\{RenderModeEnum, ContainerModeEnum};

// Inline (in-cell): always pretty raw JSON with click-to-copy
JsonColumn::make('properties')
    ->renderAs(RenderModeEnum::Tree) // used if you later switch to modal/drawer
    ->presentIn(ContainerModeEnum::Inline);

// Tree in a Drawer (with toolbar)
JsonColumn::make('properties')
    ->renderAs(RenderModeEnum::Tree)
    ->presentIn(ContainerModeEnum::Drawer)
    ->initiallyCollapsed(1)
    ->expandAllToggle() // Tree only (modal/drawer)
    ->copyJsonAction(false); // hide Copy button

// Table mode in a Modal with custom headers
JsonColumn::make('properties')
    ->renderAs(RenderModeEnum::Table)
    ->presentIn(ContainerModeEnum::Modal)
    ->keyColumnLabel('Custom Key Label')
    ->valueColumnLabel('Custom Value Label');

Sugar aliases

// Content render mode:
->asTree() // = renderAs(RenderModeEnum::Tree)
->asTable() // = renderAs(RenderModeEnum::Table)

// Container presentation:
->inlineContainer() // = presentIn(ContainerModeEnum::Inline)
->inModal() // = presentIn(ContainerModeEnum::Modal)
->inDrawer() // = presentIn(ContainerModeEnum::Drawer)

Behavior & UX

  • Inline container always renders a pretty-printed raw JSON block directly in the cell. Click the block (or press Enter/Space when focused) to copy JSON to clipboard.
  • Raw JSON strings are decoded when they contain valid JSON, so database values like {"key":"value"} can still render as structured Tree/Table content.
  • Expand/Collapse buttons only appear in Tree mode, and only for Modal/Drawer.
  • maxDepth(int) controls nesting depth rendering in Table mode.
  • filterNullable(true) filters out null values from arrays/collections. It preserves valid JSON falsy values like false, 0, "0", and empty strings.
  • characterLimit(?int) truncates long string scalars.

State handling

JsonColumn follows Filament's own state resolution first, then normalizes the value for JSON rendering. That means state(), getStateUsing(), default(), relationship state, separators, and Filament state caching continue to work as expected.

JsonColumn::make('properties')
    ->state(fn ($record) => $record->metadata)
    ->default(['status' => 'missing'])

The column accepts arrays, collections, Arrayable values, JSON strings, and scalar values:

JsonColumn::make('payload')
    ->filterNullable()

With filterNullable() enabled, only null entries are removed:

{
  "null_value": null,
  "false_value": false,
  "zero": 0,
  "string_zero": "0",
  "empty_string": ""
}

false_value, zero, string_zero, and empty_string remain visible.


In modal/drawer modes you can enable a small toolbar above the content:

JsonColumn::make('properties')
    ->asTree()
    ->inDrawer()
    ->expandAllToggle() // adds Expand all / Collapse all buttons
    ->copyJsonAction(false); // hide Copy JSON button

Labels (Table mode)

JsonColumn::make('properties')
    ->asTable()
    ->inModal()
    ->keyColumnLabel('Key')
    ->valueColumnLabel('Value');

API reference (selected)

  • renderAs(RenderModeEnum::Tree|Table) — choose how JSON is rendered.
  • presentIn(ContainerModeEnum::Inline|Modal|Drawer) — choose where it is presented.
  • asTree(), asTable() — sugar for renderAs(...).
  • inlineContainer(), inModal(), inDrawer() — sugar for presentIn(...).
  • initiallyCollapsed(int $depth = 1) — auto-collapse depth for Tree.
  • expandAllToggle(bool $on = true) — toggle Tree toolbar buttons (modal/drawer).
  • copyJsonAction(bool $on = true) — toggle Copy JSON button (modal/drawer).
  • keyColumnLabel(string), valueColumnLabel(string) — Table headers.
  • maxDepth(int) — nesting limit for Table mode nested blocks.
  • filterNullable(bool) — filter out null values while preserving falsy JSON scalars.
  • characterLimit(?int) — truncate long string values.
  • getContainerMode() / isModalContainer() / isDrawerContainer() / isInlineContainer() — container checks.

Migration from v4 → v5

Filament v5 has no breaking API changes — it adds Livewire v4 support. The upgrade is straightforward:

composer r pepperfm/filament-json:^5.0

No code changes required. All existing JsonColumn configuration works as-is.

Requirements:

  • PHP 8.2+
  • Laravel 12+
  • Filament 5.x

Version matrix

  • Filament 5.xpepperfm/filament-json:^5.0
  • Filament 4.xpepperfm/filament-json:^4.0 or ^3.0
  • Filament 3.xpepperfm/filament-json:^2.0

Your existing constraints like ^3.x or ^4.x will continue to resolve to the proper major — v5 won't auto-install unless you opt in.


Styling

The package ships a compiled CSS with soft borders, proper light/dark palette, and table grid lines. If you publish views and manually tweak Tailwind, ensure your scanner includes the package views (e.g. resources/views/vendor/filament-json/**/*.blade.php).


Customize button and modal props

The button() and modal() method accept the type of array|Arrayable|\stdClass, and implements basic properties of button and modal blade components from Filament documentation: Core Concepts - Blade Components

use PepperFM\FilamentJson\Columns\JsonColumn;
use Filament\Support\Enums\Width;
use Filament\Support\Icons\Heroicon;

$buttonConfig = literal(
    color: 'primary',
    size: Width::Medium->value
);
$modalConfig = [
    'icon' => Heroicon::OutlinedSwatch,
    'alignment' => 'start',
    'width' => Width::Medium->value,
    'closedByEscaping' => true,
    'closed_button' => false, // also accepts camel_case
];

JsonColumn::make('properties')
    ->inModal()
    ->button($buttonConfig)
    ->modal($modalConfig);

DTO schemas of components configuration:

use Filament\Support\Enums\Width;
use Filament\Support\Icons\Heroicon;

class ButtonConfigDto extends \Pepperfm\Ssd\BaseDto
{
    public string $color = 'primary';

    public Heroicon $icon = Heroicon::OutlinedSwatch;

    public ?string $label = null;

    public ?string $tooltip = null;

    public string $size = Width::Medium->value;

    public ?string $href = null;

    public ?string $tag = null;
}
use Filament\Support\Icons\Heroicon;
use Filament\Support\Enums\Alignment;
use Filament\Support\Enums\Width;

class ModalConfigDto extends \Pepperfm\Ssd\BaseDto
{
    public ?string $id = null;

    public Heroicon $icon = Heroicon::Sparkles;

    public string $iconColor = 'primary';

    public Alignment $alignment = Alignment::Start;

    public string $width = Width::TwoExtraLarge->value;

    public bool $closeByClickingAway = true;

    public bool $closedByEscaping = true;

    public bool $closedButton = true;

    public bool $autofocus = true;
}

Displaying nested data

Any options to displaying data:

JsonColumn::make('properties')->expandAllToggle()


JsonColumn::make('properties')->expandAllToggle()->inModal()


JsonColumn::make('properties')->inline()


JsonColumn::make('properties')->asTable()


JsonColumn::make('properties')->asTable()->inModal()