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

Symfony Json Schema Validation Laravel Package

outcomer/symfony-json-schema-validation

Symfony integration for validating JSON documents against JSON Schema. Adds validator constraints and services so you can enforce schemas in forms, requests, or domain objects with familiar Symfony validation workflows.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and register. The bundle follows Symfony Flex conventions:

composer require outcomer/symfony-json-schema-validation

If Flex doesn't auto-register it, add Outcomer\JsonSchemaValidation\OutcomerJsonSchemaValidationBundle to config/bundles.php. The bundle pulls in opis/json-schema transitively — do not install opis/json-schema yourself with a conflicting constraint.

Look here first:

  1. The README on the repo — it is short and is the primary source of truth for the config key names and the service alias.
  2. config/packages/outcomer_json_schema_validation.yaml after running bin/console config:dump-reference outcomer_json_schema_validation — this shows the exact schema-definition shape your version expects.
  3. bin/console debug:container | grep json_schema — confirm the validator service ID, since bundles of this size have historically renamed aliases between minor versions.

First use case — validate a webhook/API payload. Define a schema in config, point it at a JSON file, then inject the validator into a controller or message handler and validate the decoded request body before mapping it to a DTO. This is the highest-value daily use of the bundle: rejecting malformed external payloads with structured errors instead of ad-hoc isset() chains.

Implementation Patterns

Named schemas referenced from config. Keep schemas as files under config/schemas/ and reference them by name in the bundle config rather than inlining JSON in YAML. This keeps the schema diff-able, reusable across endpoints, and IDE-highlighted. A typical entry looks like a map keyed by name, with either an inline schema: object or a file:/path pointing at %kernel.project_dir%.

Constraint-style validation on DTOs. If your version exposes a validator constraint, apply it to the request DTO / value object (attribute, or annotation on older PHP). Pair this with #[MapRequestPayload]-style deserialization so schema validation runs as part of Symfony's normal validator pipeline — this means $form->isValid(), validator->validate($dto), and automatic 400s with violations all work without bespoke error handling.

Service-style validation for raw arrays. In controllers and command/message handlers, decode the body (json_decode($body, true, 512, JSON_THROW_ON_ERROR)) and pass the array to the injected validator against a named schema. This is what you want when the payload is not backed by a DTO — e.g. polymorphic payloads where the type discriminator selects the schema, or webhook handlers that must log raw input.

Schema reuse via $ref. Split large schemas into common/address.json, common/money.json and $ref them from the endpoint schemas. Keep them in one directory so relative refs resolve; if the bundle has a configurable schema root/base URI, set it once in config rather than embedding absolute paths.

Testing pattern. Validate fixtures in a functional test (good-payload → no violations, bad-payload → expected pointer in the error path). Because the library surfaces JSON-pointer-style error paths, you can assert on /properties/email rather than on free-text messages — far less brittle than asserting on Symfony violation messages.

Version schemas per API version. Name keys like orders.v1, orders.v2 and resolve the schema name from a route parameter or header. This makes breaking API changes explicit and testable without deploying schema changes to old clients.

Gotchas and Tips

  • Low adoption is a real risk. 20 stars and 0 dependents means you are close to the only user. Pin the exact version in composer.json, and consider whether writing a ~30-line service around opis/json-schema directly would be simpler and more durable. The bundle mostly wires config to OPIS — little of its value is irreplaceable.
  • Draft version mismatch is the #1 silent failure. OPIS supports draft-04, draft-06, draft-07 and 2019-09/2020-12 but the active draft depends on $schema (or an explicit option). if/then/else, const, and unevaluatedProperties will be ignored under the wrong draft rather than erroring — schemas that "pass" may not be validating what you think. Assert your draft explicitly in each schema file.
  • $ref resolution and base URI. Relative refs resolve against the schema's base URI, which for a file: source is often the file's directory — but some wiring passes raw strings where OPIS has no base. Symptom: "unable to resolve reference" or silent fallback. Fix by loading schema files with a consistent base URI, or inlining $id at the top of each schema.
  • OPIS errors are not Symfony violations. Raw OPIS error objects carry keyword, pointer, property and a message. If you skip the bundle's violation conversion, $errors = $validator->validate($dto) will hold raw OPIS objects and getMessage() / form rendering will break. Wrap errors into ConstraintViolation (or Symfony's own Json constraint if you swap) before returning a 400.
  • Schema compile cost. OPIS compiles schemas on first use. For long-running workers (Messenger consumers) that is fine; for a high-traffic endpoint it can show up. Cache compiled validators per schema name in a small factory service rather than re-fetching from the container per request, and always enable OPIS's schema cache in dev if available.
  • Cache clearing after schema edits. Schema files are not Twig/Validator resources as far as Symfony's cache is concerned. If you inline schemas in YAML, cache:clear handles it; if you point at files, OPIS may cache compiled copies under var/cache — clear after editing, or you'll debug a schema change that "isn't applied".
  • Extension point to watch: the bundle's violation-message formatter. That's where you inject i18n, strip internal pointer noise from user-facing messages, and map OPIS keywords to friendly text. Keep that translation in one service so error responses are consistent across DTO-constraint and service-style usages.
  • Do not mix with Symfony's Json constraint. Two JSON validators in one codebase (Symfony's Json for syntax, this bundle for schema) is fine, but using both for schema validation produces inconsistent error shapes in the same response. Pick one for schema work and route syntax-only checks through json_decode(..., JSON_THROW_ON_ERROR).
  • Log the failing payload (redacted) alongside the violations on 400s for the first weeks after rollout. Schema bugs are usually over-strict required or pattern rules, and without the payload plus the JSON pointer you cannot tell a client bug from a schema bug.
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