Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Filament Json Field Laravel Package

codebar-ag/filament-json-field

Codebar's Filament JSON Field adds a dedicated JSON editor to Filament forms, with syntax highlighting, validation, formatting, and a clean editing experience. Ideal for settings, metadata, and API payloads, it makes structured JSON easy to manage in Laravel admin panels.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the package into an existing Filament 3/4 application:

composer install codebar-ag/filament-json-field

There is no service provider to register manually on modern Laravel package discovery, but confirm CodebarAg\FilamentJsonField\JsonFieldServiceProvider is listed in bootstrap/providers.php (Laravel 11+) if auto-discovery is disabled. Ensure your model casts the target column to array or json so Filament receives a PHP array rather than a raw string:

protected function casts(): array
{
    return ['metadata' => 'array'];
}

Where to look first:

  1. The README for the field's fluent API (formatOnBlur, height, editor options, etc.) — it is short and changes between releases.
  2. src/Forms/Components/JsonField.php — everything is in this one class; skim the setters to see what is actually configurable in your pinned version.
  3. tests/ — the fastest source of truth for how state is hydrated and dehydrated.

First use case — editing a JSON blob on a resource:

use CodebarAg\FilamentJsonField\Forms\Components\JsonField;

JsonField::make('metadata')
    ->label('Metadata')
    ->formatOnBlur()
    ->required();

That's the whole setup. The field renders an editor, loads the decoded array, and dehydrates a JSON-encoded value on save.

Implementation Patterns

Standard resource form. The idiomatic usage is a single JSON column on a model, cast to array, edited through a normal Filament form. Keep validation in the field's rules() so the user gets an inline error instead of a 500 on save:

JsonField::make('settings')
    ->rules(['json'])
    ->formatOnBlur()
    ->columnSpanFull();

Formatting workflow. Most teams pair the field with an explicit format action so the stored JSON is always canonical. If the package exposes formatOnBlur() / autoFormat(), prefer the blur variant — formatting on every keystroke is noisy for large payloads and fights the cursor position.

Conditional/partial editing. For "advanced settings" style UIs, wrap the field in a Section that is collapsed by default and gate it with ->visible(fn ($record) => $record?->is_admin) or ->hidden(fn (Get $get) => ! $get('show_advanced')). JSON editing is a power-user affordance; don't put it in the primary path for non-technical users.

Read-only / display contexts. On the ViewRecord page, ->disabled() (Filament's read-only state) is usually cleaner than a TextEntry, because you keep the same highlighting and formatting the editing page has. Avoid rendering JsonField in table columns — use TextColumn::make('metadata')->formatStateUsing(...) or a badge/limit instead.

Mutation before save. When the underlying column expects a string but your model doesn't cast it, normalize in the page rather than in the field:

protected function mutateFormDataBeforeSave(array $data): array
{
    $data['settings'] = json_encode($data['settings'], JSON_PRETTY_PRINT);
    return $data;
}

This is also the correct place to enforce key ordering (ksort) if downstream systems diff the JSON.

Integration with actions and repeaters. JsonField is a normal Filament component, so it works inside Repeater, Action::make()->form(), and relation-manager schemas. In repeaters, give each instance a clear ->label() — the browser's DOM id is generated from the name and nested array paths (form.repeaters.settings.0.json) look identical to users.

Testing. Use Filament's form assertions. Because the field state is an array, assert with the decoded shape:

livewire(EditSettings::class, ['record' => $record])
    ->fillForm(['metadata' => ['foo' => 'bar']])
    ->call('save')
    ->assertHasNoFormErrors();

$this->assertSame(['foo' => 'bar'], $record->fresh()->metadata);

If your cast is array, avoid asserting on the raw attribute — Eloquent will re-decode it and spacing/order differences will make the test brittle.

Gotchas and Tips

  • null vs [] vs {}. JSON round-trips are lossy in PHP: {} decodes to an empty array, which re-encodes as []. If consumers distinguish an object from an array (common with third-party APIs), either don't cast to array and hand the field a raw string, or normalize explicitly before saving.
  • Validation is per-field, not per-key. A rules(['json']) check tells the user the blob is malformed but not which key broke a business rule. For anything with a known schema, add a custom closure rule or validate on after() in the form and map errors back with ->addError('data.metadata', ...).
  • Key ordering churn. Decode → encode does not preserve insertion order semantically, and a user hitting save without changes can produce a spurious diff in git/audit logs. ksort (recursively) in mutateFormDataBeforeSave is the cheapest fix.
  • Large payloads. Syntax highlighting on multi-megabyte JSON will lock the browser tab. Cap the readable size with a rule, or switch to an upload/import flow for big documents. Also watch post_max_size and Filament's Livewire payload limits before blaming the component.
  • Editor assets and CSP. The visual editor is JS-driven. If you run a strict Content-Security-Policy or a non-standard asset pipeline (Vite base path, subdirectory deploys), the editor may silently fall back to a plain <textarea>. Check the browser console first — the field still works, so it's easy to misdiagnose as "styling."
  • State mismatch on hydration. If the form is blank despite data existing, verify the cast. A string column cast to array is fine; a json column without a cast passes a string into the field and you'll see escaped quotes.
  • Disabled vs read-only vs hidden. Filament's disabled() still submits the value in some versions and not others; if you're locking a field but relying on the existing value, confirm the save path preserves it rather than overwriting with null.
  • Pinning. This is a low-traffic package (single-digit stars, one release in the last period). Pin an exact version in composer.json, and run the upgrade with a smoke test on the edit page — a Filament major bump is far more likely to break this than a patch release of the package itself.
  • Extension points are thin. If you need schema-aware completion, diffing, or search, you'll be wrapping the underlying editor rather than configuring this field. Check the class for public setters before assuming an option exists; if not, publish/extend the view (Blade component) instead of forking.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource