wikimedia/json-codec
A PHP library from Wikimedia for converting objects to and from JSON using schemas, with validation, custom codecs, and typed deserialization to keep JSON handling consistent and safe.
Architecture fit. JsonCodec is a small, framework-agnostic PHP utility library: static JsonCodec::encode() / JsonCodec::decode() entry points, a typed exception hierarchy (JsonParseException, JsonSchemaException, JsonEncodeException), and optional JSON Schema validation on decode. It has no framework coupling, no global state, and no service container assumptions, so it slots into a Laravel application as a leaf dependency rather than an architectural component. It does not replace Laravel's internal JSON handling (session, cache, queue payloads, Eloquent casts) — it is a targeted substitute for hand-rolled json_decode() calls on untrusted or externally-sourced payloads. That is a narrow but legitimate niche.
Integration feasibility. High technically, low politically. Technically: composer require wikimedia/json-codec, a thin wrapper service, and a custom Eloquent cast gets you strict decoding in an afternoon. The only transitive dependencies are ext-json and Wikimedia's own at-ease (error-handler suppression), both trivially satisfiable on any Laravel-supported PHP version. The blocker is licensing: GPL-2.0 is copyleft and is not compatible with the MIT-licensed Laravel ecosystem or with proprietary application code that is distributed to customers. For a SaaS deployment where the code is never conveyed, this is defensible; for an on-prem or shipped product, legal will almost certainly reject it. This must be resolved before any engineering time is spent.
Technical risk.
json_decode($s, true, 512, JSON_THROW_ON_ERROR), which covers the exception-based decoding story that was JsonCodec's original differentiator. The residual gaps are real but narrow: strict rejection of duplicate object keys, strict RFC 8259 validation, and bundled schema validation.$ref, oneOf, patternProperties, format assertions) are actually implemented before committing schemas to it. If coverage is thin, opis/json-schema is a more complete and permissively-licensed alternative.Key questions.
JSON_THROW_ON_ERROR — is duplicate-key rejection an actual requirement, or an assumed one?Stack fit. Composer-native, PSR-4, PHP-version constraints aligned with a modern Laravel baseline. No build step, no extension beyond ext-json, no conflict with Laravel's autoloading or package discovery. It is a library, not a package — expect zero Laravel affordances: no service provider, no facade, no config file, no config/json-codec.php. You build and own that surface.
Migration path. Do not attempt a codebase-wide replacement of json_decode. Sequence it:
JsonDecoder service (interface + implementation) bound in a service provider. This is the seam that lets you swap to JSON_THROW_ON_ERROR or opis later without touching call sites — and it is what makes the GPL dependency removable if legal reverses course.StrictJson Eloquent cast for the one or two models that ingest externally-sourced JSON, leaving framework-internal casts untouched.Compatibility. Verify the pinned PHP floor against your oldest supported runtime and against Laravel's own constraints; the library tracks MediaWiki's LTS, which may lag your framework's minimums or lead them. Confirm PHPUnit/static-analysis compatibility (it ships no Laravel testing helpers; you'll write your own fakes around the exceptions). Confirm behavior under Laravel's error handler — JsonCodec depends on at-ease for warning suppression, and interaction with Laravel's set_error_handler chain should be tested explicitly rather than assumed.
Sequencing. Legal sign-off → wrapper service + tests → single pilot ingestion path → observability on rejection reasons → evaluate schema validator coverage → expand or abandon. Do not let schema definition work start before the coverage audit; schemas written against unimplemented keywords are wasted effort.
Maintenance. Low churn, stable public API, Wikimedia-funded. The cost is not in upgrading the library but in owning the wrapper, the schemas, and the exception-to-HTTP mapping — all of which are your code and your on-call surface. Track the Gerrit repo directly; the GitHub mirror will not surface release notes or security advisories promptly.
Support. No GitHub issue tracker, no community forum, no Laravel-ecosystem familiarity. Escalation is Gerrit and Wikimedia's Phabricator. Realistically, your team debugs this itself. Budget for that in the ramp-up estimate — it's a small library, so this is tractable, but it is not zero.
Scaling. Runtime cost is essentially native json_decode plus error-checking overhead — negligible. The measurable delta is schema validation, which is per-payload and proportional to schema size and nesting depth; benchmark against your p99 payload before enabling it on a hot path. No memory, connection, or concurrency concerns; the library is stateless and safe under Octane/Swoole style workers.
Failure modes.
decode() on an untrusted path can throw. Unmapped, this converts a malformed partner payload into a 500 and a page. Wrap at the boundary and map to 400 with a reason code.Ramp-up. Half a day for a mid-level engineer to read the API surface and exception hierarchy; one to two days to build and test the wrapper, cast, and middleware. Schema authoring is the real cost and depends entirely on how much of the schema vocabulary the library actually implements. Net: a low-effort, low-blast-radius addition that solves a genuine but narrow correctness problem — worth doing only if legal clears GPL-2.0 and only if the strictness requirement is concrete rather than aspirational.
How can I help you explore Laravel packages today?