stepanenko3/nova-json
stepanenko3/nova-json provides a JSON field for Laravel Nova, making it easy to edit and display structured JSON data directly in resource forms and detail views. It simplifies managing JSON values in the Nova admin panel.
Install with Composer alongside Laravel Nova:
composer require stepanenko3/nova-json
No service provider or config publishing is required. Start by reading the package README and src/JSON.php; the field is intentionally small, and most behaviour is inherited from Nova's own field classes.
The first use case is replacing a raw JSON textarea with structured Nova fields. Cast the column on the Eloquent model ('meta' => 'array' or 'json'), then group nested Nova fields under the JSON field:
use Stepanenko3\NovaJson\JSON;
JSON::make('Meta', [
Text::make('Title'),
Textarea::make('Description'),
Boolean::make('Enabled'),
])
Nova stores the group as a single JSON column while the user edits individual inputs. The JSON field is essentially a container: child fields keep their normal validation, visibility, and authorization behaviour, but their attribute names are resolved relative to the parent JSON column using dot notation. If you need arbitrary key/value pairs rather than a fixed schema, use the package's key/value variant instead of the grouping field.
Grouped schemas. Define the shape once in fields() and keep child names stable. Moving a child key renames the stored JSON key and will orphan existing data unless you migrate it. Prefer explicit child fields over a generic editor for anything that needs validation.
Key/value maps. Use the key/value field for user-defined configuration maps, feature flags, or metadata where keys are not known ahead of time. Treat it as unordered; do not rely on insertion order being preserved across saves.
Validation. Apply rules to the nested attributes using dot notation:
JSON::make('Meta', [
Text::make('Title')->rules('required|max:120'),
Number::make('Priority')->rules('integer|min:0'),
])
Because the parent field is not a scalar input, put validation on the children rather than on the container.
Index and detail views. JSON columns render poorly by default. Use ->onlyOnForms() for large groups, or a custom displayUsing() callback on the parent to render a summary. Child fields can still use ->hideFromIndex() individually.
Partial updates. Nova submits only the fields present in the request. If your JSON column contains keys not represented in the form, a normal save can drop them. Either represent every key or override filling with fillUsing() to merge the incoming payload with the existing array. This is the most common source of silent data loss with any JSON-backed field.
Nesting and reuse. JSON groups can be nested, but each level adds attribute-resolution complexity. For reusable field sets, extract a method or field class and reuse it; do not duplicate names across sibling groups.
Upgrading. v4.1.3 is a patch release that fixes a strict-type issue in resolveAttribute. It is a safe drop-in upgrade from v4.1.2 with no migration or API changes. The fix matters if your app runs with declare(strict_types=1) or if Nova resolves a nested attribute name that is not a plain string (for example during name/label resolution): previously that could raise a TypeError.
array/json cast on the model, Nova will receive a string and child fields will not resolve. This is the first thing to check when nested fields appear empty.resolveAttribute and strict types. The v4.1.3 fix targets non-string attribute values being passed into resolveAttribute. If you were pinned to v4.1.2 and saw TypeError exceptions when rendering forms or resolving field names, upgrade.null JSON column may resolve children as null; combine ->nullable() on children with sensible defaults, or normalise the attribute in the model's accessor.settings.title inside a JSON group become meta.settings.title. Keep naming shallow and avoid reusing a child name that already exists as a top-level model attribute.Array or truncated JSON. Always provide a displayUsing() formatter for index views.searchable(); use a generated column or model accessor if you need filtering. Database-level JSON queries also vary by driver (MySQL vs PostgreSQL vs SQLite).fill() implementation before relying on partial form submissions. If the field replaces the whole JSON value, add a merge in fillUsing().JSON, key/value fields). Alias imports if your application already has a JSON field or uses Nova's built-in KeyValue.How can I help you explore Laravel packages today?