armincms/json
A Laravel package that simplifies working with JSON data in Eloquent models. Fluent helpers let you read, write, query, and cast JSON columns, making nested structures and dynamic attributes easier to manage throughout your application.
Gate on compatibility before you install anything. The last release was June 2020 — Nova 2/3, Laravel 6/7, PHP 7.x territory. A current stack (Nova 4/5, PHP 8.1+) will most likely fail resolution outright:
composer require armincms/json --dry-run
composer why-not armincms/json
If Composer refuses to resolve, stop treating this as a dependency and treat it as source material — read the Gotchas section before you spend an afternoon fighting it.
Install and publish the front end. A Nova field is a PHP class plus a compiled Vue component. If the asset never publishes, you get a blank cell or a bare textarea:
composer require armincms/json
php artisan vendor:publish --tag=nova-assets # confirm the actual tag in src/
Look inside src/ for the service provider — the README is thin and the publish tag is defined there, not documented.
Read the field class before writing a single resource. You need three facts from the source:
Armincms\Json\Json vs something else — don't guess).Field vs Text — this determines rules(), resolveUsing(), etc.).That one read saves an hour of "renders but doesn't save" debugging later.
First use case: one low-risk resource on a branch. Point it at a settings or metadata JSON column, save, reload, and inspect the raw column value in tinker. Confirm the round-trip and the storage format (double-encoded string vs object) before touching anything real. This is the whole spike — a few hours, not a sprint.
Basic wiring.
// app/Nova/Setting.php
use Armincms\Json\Json; // confirm FQCN from src/
public function fields(Request $request)
{
return [
Json::make('Payload')
->rules(['required', 'json', 'max:65535'])
->help('Arbitrary JSON. Validated before save.'),
];
}
Decide the cast strategy first — this is the pattern that matters. If the model declares protected $casts = ['payload' => 'array'] and the field writes a JSON string, you can double-encode. Pick one of:
array cast — but only if the field's write path is cast-aware (check the source). Otherwise wrap the field.Verify after a save, on both create and update paths:
$setting->refresh()->payload; // what the model sees
DB::table('settings')->where('id', $setting->id)->value('payload'); // what's actually stored
Wrap it in your own field class. Even if you install the package directly, subclass it so upgrades and fixes have a single seam:
namespace App\Nova\Fields;
class JsonEditor extends \Armincms\Json\Json
{
public function rules()
{
return array_merge(parent::rules(), ['json', 'max:65535']);
}
}
Now a Nova upgrade, a fork, or a full replacement is one file, not every resource.
Enforce schema server-side. The field is a text box; it does not validate your domain. json catches syntax errors. For a bounded shape, add a custom rule:
Json::make('Payload')->rules([new ValidSettingsSchema()])
Scope authorization — the field is not a security boundary. Restrict visibility/editing and mirror it in the policy:
Json::make('Payload')
->canSee(fn ($request) => $request->user()->isOperator())
->canEdit(fn ($request) => $request->user()->isOperator());
Escape on the way out. The field only gets you into the column; every consumer is a separate XSS decision. {{ $setting->payload }} is safe; {!! json_encode(...) !!} over user-entered content is not.
Instrument during the spike. resolveUsing / fillUsing let you log what the field reads and writes — invaluable for cast bugs:
Json::make('Payload')
->resolveUsing(fn ($v) => tap($v, fn ($x) => logger('json read', ['v' => $x])))
->fillUsing(fn ($req, $model, $attr, $reqAttr) =>
$model->{$attr} = $req->input($reqAttr));
(Signature varies by Nova major — verify against your version.)
json rule plus schema validation, semantically wrong JSON persists quietly and breaks every downstream reader — backfill territory.->make('Payload') matches an actual column and whether the cast is eating the value. Log with fillUsing to confirm the request arrives.array casts is the single most common data bug with fields like this. Test create and update, and inspect the raw column, not the hydrated property.{!! !!} on admin-entered JSON is real. Audit every consumer, not just the field.src/ and confirm — if they're not there, implement them as model accessors/mutators and stop relying on the field for anything but editing.internal/nova-json-field) via a VCS repository entry, keep the MIT attribution, and name an owner. An unowned fork fails silently during a Nova upgrade and becomes a mid-migration blocker.max: rule and a "one sub-document, not a whole config tree" convention.How can I help you explore Laravel packages today?