joipolloi/json-validation-bundle
A Symfony bundle for validating JSON payloads against schemas, helping you enforce request structure and return clear validation errors in your PHP applications.
Architecture fit. There is a framework mismatch that dominates the entire evaluation: joipolloi/json-validation-bundle is a Symfony framework bundle, not a Laravel package. Its value is delivered through three Symfony-specific mechanisms — bundle registration in bundles.php, a Doctrine annotation read by an annotation reader wired into sensio/framework-extra-bundle's argument resolver, and a kernel/controller event listener that intercepts the payload before the controller action fires. Laravel has no bundle registration, no annotation-driven argument resolution, and no equivalent interception point at controller invocation. Roughly 60–80% of the package is scaffolding with no destination in a Laravel application. The remaining 20% — "decode the JSON body, validate against a JSON Schema, reject with a structured error" — is genuinely valuable and reproducible in under 100 lines.
Integration feasibility. Low as a dependency, high as a pattern. composer require would install cleanly and then produce dead code: service definitions, compiler passes, and the annotation reader would never be invoked. Forcing it in would require an adapter that manually instantiates the validator, shims Symfony's HttpFoundation\Request onto Illuminate\Http\Request, and mimics the event dispatcher — a shim that leaks through the call stack and will fracture on getContent()/getPayload() semantics. The realistic path is extraction, not integration: the underlying engine is almost certainly justinrainbow/json-schema, and re-implementing the bundle's behaviour in Laravel is a custom validation rule or FormRequest subclass. Cheaper than any adapter, and maintainable by the team that owns it.
Technical risk. High, and concentrated in provenance. Four stars, zero dependents, and a repository that reads as a 2015–2017-era artifact. Specific exposures:
Key questions.
array and dot-notation rules genuinely fall short, or is the payload flat enough that first-party rules suffice?application/problem+json with JSON Pointer paths to failing fields, or is a 422 with a message sufficient?Stack fit. Poor as shipped. Mapping the bundle's concerns onto a Laravel stack:
| Bundle concern | Symfony mechanism | Laravel equivalent |
|---|---|---|
| Registration | Bundle class + kernel | None — a service provider has nothing to bind |
| Schema declaration | Doctrine annotation on controller | FormRequest::rules(), PHP attribute, or config map |
| Interception | Kernel/controller event listener | Middleware or FormRequest authorization/validation |
| Payload access | Request::getContent() |
$request->json()->all() / $request->input() |
| Error response | Symfony JsonResponse + violations |
ValidationException → 422 handler |
Every row requires translation, and there is no row where the package does work Laravel does not already do.
Migration path — rebuild, don't bridge.
justinrainbow/json-schema — or preferably opis/json-schema for better performance and draft-07/2019-09 support — in a scratch branch and validate three real payloads against their schemas. This de-risks the only technically uncertain element (dialect coverage) without touching production code.JsonSchema validation rule (via Validator::extend or a Rule object) that accepts a schema path, validates the decoded array, and maps violations into Laravel's message bag using JSON Pointer strings as attribute names so frontend field-level error mapping keeps working.FormRequest base class so endpoint classes declare protected function schema(): string and inherit validation, 422 shaping, and application/problem+json content negotiation.Compatibility. Two hard gates before step 2: confirm the chosen engine supports the JSON Schema draft your schemas are authored in (draft-04 vs draft-07 vs 2019-09 differ materially on exclusiveMinimum, const, and if/then/else), and confirm the engine is compatible with your PHP runtime (8.1/8.2/8.3) and under active security maintenance. opis/json-schema is the stronger choice on both axes; the bundle's presumed engine is the weaker one.
Sequencing. Validation lands after the schema artifacts stabilise and before any consumer-facing rollout that depends on contract enforcement — building the rule first and the schemas second inverts the dependency and guarantees churn. Run it in shadow mode (validate, log violations, do not reject) for one release cycle on high-traffic endpoints to catch schema/payload drift before it becomes a 422 outage. Sequence the work behind authentication ordering, not alongside it.
Maintenance. Adopting the bundle transfers a maintenance liability with no upstream counterpart. Forking means owning a Symfony bundle you do not want; porting means owning ~100 lines you fully understand. The port is the lower total cost of ownership by a wide margin and removes a dependency from supply-chain review entirely. Steady-state cost of the first-party version is near zero, revised only when a JSON Schema draft changes or a dependency CVE lands.
Support. There is no support channel. Four stars and zero dependents means no Stack Overflow corpus, no issue triage, and no realistic prospect of an upstream fix to a bug you report. Every defect becomes an in-house defect, discovered in production, on a code path that processes untrusted input — an unfavourable risk profile for a component sitting at the request boundary. The port converts that unknown into a known, owned surface.
Scaling. Schema validation is CPU-bound and synchronous: parse schema, validate payload. On multi-MB bodies or deeply nested arrays this is measurably more expensive than Laravel's native scalar rules, and recursive schemas can be pathological. Mitigations: cache compiled schemas (schemas are static per endpoint — parse once per worker via a container singleton), cap body size at the web server or middleware before validation runs, and enforce maxDepth/maxItems where the engine supports it. The operationally significant failure mode: an unbounded maxItems on an array schema is a cheap DoS vector. This risk is identical whether you use the bundle or a port — it is a property of schema validation, not of this package.
Failure modes.
additionalProperties: false) and clients sending benign extra fields start receiving 422s. Mitigate with shadow mode before enforcement.justinrainbow/json-schema update or PHP minor upgrade breaks the abandoned bundle with no upstream fix. This is precisely the failure mode the port eliminates.Ramp-up. For the bundle as shipped: effectively not rampable. A Laravel engineer would spend more time reverse-engineering Symfony's annotation and event machinery than writing the replacement. For the port: half a day for a mid-level engineer comfortable with Laravel validation, plus a day for whoever owns the schema artifacts to confirm dialect and draft. The practical recommendation is to reject the dependency and adopt the pattern — a small, low-risk engineering task with an identical outcome and none of the supply-chain exposure.
How can I help you explore Laravel packages today?