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

Json Validation Bundle Laravel Package

hrombach/json-validation-bundle

A Symfony bundle for validating JSON payloads against configurable rules and schemas, helping you reject malformed data early and surface clear, structured errors before it reaches your application logic.

View on GitHub
Deep Wiki
Context7

Getting Started

Framing note before anything else: hrombach/json-validation-bundle is a Symfony bundle, not a Laravel package. It has no ServiceProvider, no auto-discovery, no config/*.php hooks. For a Laravel codebase you should treat it as a reference implementation rather than a dependency — it is a thin wrapper around justinrainbow/json-schema, and you get the same functionality by requiring that library directly (~1 line in composer.json) plus a small binding in your own AppServiceProvider.

If you still want to inspect it:

  1. composer require hrombach/json-validation-bundle (in a scratch Symfony app — it will install cleanly in Laravel, it just won't do anything).
  2. Open Resources/config/services.* first. That file is the entire bundle. It tells you the service ID, the constructor args (usually a schema path or a Validator instance), and whether anything is configurable via Configuration.php. For a bundle this limited, that is the whole API surface.
  3. Check DependencyInjection/ for the extension class — if there is no meaningful Configuration node, you have no runtime config and the schema location is likely hardcoded or injected by the app.
  4. First use case to evaluate: take a representative JSON payload from your API (e.g. a webhook body or a PATCH /orders/{id} request), write a draft-07 schema for it, and validate it. That tells you in ten minutes whether the wrapper adds anything over calling JsonSchema\Validator yourself.

The pragmatic Laravel equivalent — and what I would actually ship — is:

// composer require justinrainbow/json-schema
$this->app->bind(\JsonSchema\Validator::class, fn () => new \JsonSchema\Validator());

Then inject it wherever you need schema validation.

Implementation Patterns

1. Bind the underlying validator, not the bundle. In AppServiceProvider::register() bind JsonSchema\Validator (or a small JsonSchemaValidator wrapper of your own). This gives you constructor injection in jobs, actions, and form requests without dragging Symfony DI into the picture.

2. Validate at the boundary, hydrate after. Use schema validation as a guard in a FormRequest or middleware, then map to a DTO. Schema validation catches shape/type errors; Laravel's Validator catches business rules. Don't try to express business rules in JSON Schema — if/then, dependentSchemas, and oneOf get unreadable fast.

$data = json_decode($request->getContent()); // object, NOT assoc array
$validator->check($data, (object)['$ref' => 'file://'.base_path('schemas/order.json')]);
if (! $validator->isValid()) {
    throw ValidationException::withMessages(
        collect($validator->getErrors())->mapWithKeys(fn ($e) => [$e['property'] => $e['message']])->all()
    );
}

3. Keep schemas as files, resolved by absolute URI. Store them under resources/schemas/ (or better, a dedicated schemas/ root that is also copied into your container image). Reference them via $ref with a file:// URI or a resolvable base. Relative $refs between schemas only work if the base is set correctly — pass the full path, don't rely on CWD.

4. Registry pattern for many schemas. Rather than a single schema path (which is what a bundle like this typically assumes), wrap a small SchemaRegistry that maps a logical name to a file path, and cache decoded schemas in memory or in Laravel's cache. json_decode + $ref resolution is not free, and the same schema will validate thousands of payloads.

5. Use it in queued-job payloads and webhook receivers. This is where JSON Schema genuinely earns its keep in a Laravel app: upstream systems send you shapes you don't control, and you want to fail loudly and specifically (pointer, constraint) rather than with a TypeError deep in a job. Validate at the top of handle() and mark the job failed with a readable reason.

6. In tests, assert on failure pointers, not messages. getErrors() returns property, pointer, message, constraint. Assert on pointer and constraint. Messages are library-version dependent.

Gotchas and Tips

  • Zero stars, zero dependents, MIT, no CI badges. Treat the bundle as sample code. The risk is not the license, it is that a wrapper around a library you can call directly is a liability with no upside. Copy the service definition into your own provider and move on.
  • justinrainbow/json-schema is legacy-maintained. It works, but it lags on schema drafts and modern spec features. If you are starting fresh, opis/json-schema is the better long-term choice and has a cleaner API ($validator->validate($data, $schema) throws or returns errors). Consider this before adopting the underlying lib the bundle pins.
  • json_decode must produce objects, not assoc arrays, for justinrainbow. Passing an associative array to check() produces confusing type errors because the library expects stdClass for object schemas. Use json_decode($json) (no true flag) or cast with json_decode(json_encode($data)).
  • check() returns void. It is not a boolean. Always follow with isValid() and getErrors(). This trips people up when porting examples.
  • format is not asserted by default in older versions of the underlying library. "format": "email" will pass for garbage unless you configure the format constraint factory. Do not assume format validation is on; if it matters, assert it in a Laravel rule afterwards.
  • Draft mismatch is the most common silent failure. A $schema of draft-04 with exclusiveMinimum: true vs a numeric exclusiveMinimum (2019-09) will behave differently or error. Pin the draft in every schema and keep the library version pinned in composer.lock.
  • $ref resolution is the debugging black hole. If validation "passes" everything, check that your $ref actually resolved — an unresolvable $ref in some versions fails open or throws a non-validation exception that your isValid() check never sees. Log the resolved schema once in a test.
  • Error mapping is manual. There is no Laravel error-bag integration, no MessageBag. getErrors() gives you a flat list with JSON pointers (/items/0/price); you need to convert those to dot-notation field names yourself if you want them to line up with form fields.
  • Empty schema {} vs absent schema null. {} validates everything, null/missing usually throws. If you have optional validation, gate on the file's existence explicitly rather than passing a possibly-null path.
  • Extension point if you do keep it: decorate the service in a Symfony app, or just replace the definition. In Laravel there is nothing to extend — the correct "extension" is your own class wrapping JsonSchema\Validator, which is exactly what the bundle is.
  • Caching: justinrainbow does not cache resolved schemas across requests. In a Laravel app under load, memoize the decoded schema in a singleton or Cache::remember keyed on md5($schemaContents); otherwise you are re-parsing the same file on every request.
  • Do not use this for validating your own outgoing JSON. Serialization tests + PHP types already cover that. Save schema validation for untrusted, external, or versioned payloads.
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.
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core