karriere/json-decoder
JsonDecoder maps JSON into typed PHP objects, handling nested objects, arrays, scalar casting, required fields, and custom decoders. It turns API responses and config files into predictable, IDE-friendly classes for safer, cleaner PHP code.
Architecture fit. karriere/json-decoder is a framework-agnostic, plain-PHP hydration library: given a JSON string and a target class, it maps keys onto typed properties (docblock/attribute-driven, including nested objects and arrays of objects). That makes it a natural fit for an anti-corruption layer in a Laravel app — e.g., decoding third-party API responses, webhook payloads, or queue message bodies into DTOs before they reach domain services. It is not a fit for Eloquent model hydration, request validation, or anything that expects a Laravel service provider out of the box; there is no Illuminate dependency and therefore no config, facade, or publishable assets. Nothing in v5.1.0 changes this — the release is purely a runtime-support adjustment, not an architectural one.
Integration feasibility. High, but the runtime floor moved. composer require karriere/json-decoder, instantiate the decoder (or bind it as a container singleton), and call decode($json, MyDto::class). No migrations, no middleware, no env vars. As of v5.1.0 the package supports PHP 8.2+ (8.5 added, 8.0 and 8.1 removed), so the prerequisite is now a PHP 8.2 runtime floor rather than the 8.1 assumed previously. PSR-4 autoloading for your DTO namespace remains the only other prerequisite. Any app or CI runner still on 8.1 will fail Composer resolution against this version — pin the last 5.0.x release if you cannot move the runtime.
Technical risk.
composer update can silently raise your effective runtime floor. This raises the cost of loose version constraints: pin to ^5.1 deliberately, or to an exact minor, and let Renovate/Dependabot surface bumps for review rather than auto-merging.spatie/laravel-data (Laravel-native, large community, validation built in) and symfony/serializer (foundation-backed) before committing broadly. Note that those alternatives have their own PHP-floor cadence, so this is not a differentiator in either direction.Key questions.
composer.json-only diff? (Confirm via the diff, not the changelog.)?Class nested objects in the version we would pin?composer.lock (serializer, data-mapper, or validation packages)?Stack fit. PHP 8.2+ (8.2–8.5 supported), Composer 2, Laravel 9–12 (implicitly, since the package has no framework coupling — but note Laravel 9 still supports PHP 8.0/8.1, so this package effectively narrows you to Laravel 9.32+ or Laravel 10+). Best placed in an infrastructure layer: an Http/Integrations/<Vendor> namespace where response classes are plain DTOs, consumed by services via an interface. Keep DTOs out of controllers and away from Eloquent.
Migration path. Unchanged in shape and now more clearly justified. Do not sprinkle new JsonDecoder() through the codebase. Define a thin internal contract — e.g. App\Support\Hydration\JsonHydrator with hydrate(string $json, string $class): object — and implement it with this package. That gives three benefits: (a) a single swap point if we later move to spatie/laravel-data or symfony/serializer, (b) a place to add strict-mode validation and logging, and (c) testability with fixture JSON. The v5.1.0 runtime-floor bump is exactly the kind of change the adapter boundary does not protect you from — it is a Composer-level constraint, not an API-level one — so pair the adapter with a pinned version.
Compatibility. No illuminate/* constraints means no version pinning against Laravel, which is good, but also means Laravel compatibility is untested by the maintainer — we own that verification. New in this release: the php constraint is now effectively ^8.2, so run composer why-not karriere/json-decoder 5.1.0 against the lock file and confirm every environment (local, CI, staging, prod, queue workers, scheduled-task containers) meets the floor before bumping. If you build container images, the base image tag must be 8.2 or later — a stale php:8.1-fpm base is the most likely failure point. Add PHP 8.5 to the CI matrix only once the rest of the dependency tree supports it. Keep it in the existing composer audit/license-scan step, and if we already ship symfony/serializer or jms/serializer, confirm there's no class-name or annotation-reader collision.
Sequencing.
JsonHydrator, add fixture-based tests, wire the singleton binding, pin the exact version in composer.json (prefer ^5.1 with a reviewed lock, not * or ^5.0).Maintenance. Small code surface, low churn, but the release cadence has now demonstrated a specific pattern: minor releases can move the PHP floor. Budget a recurring half-day per quarter for upgrade review, and treat version bumps as requiring a runtime check, not just a changelog skim — add "PHP floor changed?" to the upgrade checklist. Keep the adapter boundary so API-level changes are contained; keep the version pinned so runtime-level changes are contained. Maintain a documented fallback: because the package is small, a vendored fork under our namespace is a viable 1–2 day contingency if the maintainer disappears — and a fork also lets us keep 8.1 support if we are ever forced to.
Support. Community-only: GitHub issues, no SLA, no paid support. Internal ownership must be explicit — assign a named engineer as the package owner, and record it in the service catalog. The 8.5 addition is a mild positive for the support story: it shows the maintainer reacts to upstream PHP releases, which is the single best leading indicator that they will react to security issues too. Escalation path is still "fork it," so the fork procedure should be written down before it's needed.
Scaling. Unchanged. Decoding is CPU-bound and reflection-heavy. For low-volume API clients and webhook handlers (hundreds to low thousands per day) it's a non-issue. For batch jobs or high-throughput queues, benchmark first: if a single decode exceeds ~1 ms at our payload sizes, consider caching decoder instances (they're stateless), batching, or generating hydrators. Memory footprint is negligible; the risk is latency under volume, not RAM. Note that a mandatory PHP 8.2+ runtime usually brings a small performance win on its own, so the benchmark numbers from the spike may look slightly better than they would have on 8.1 — record the runtime alongside the results.
Failure modes.
composer update that pulls 5.1.0 onto a PHP 8.1 host fails at install time, not runtime — usually caught in CI, but it will bite if any long-lived environment (a legacy queue worker image, a sidecar) lags the main app. Detect via the runtime floor audit and by pinning the version."123" into int, numeric into string, arrays into single objects — verify and lock behaviour with tests.Ramp-up. Low: a mid-level Laravel developer is productive in half a day. The README covers the core API; the real onboarding cost is our internal conventions (DTO location, adapter usage, strict-validation rule, fixture-test pattern, pinned-version policy). Write a short internal "how we decode JSON" doc and one reference DTO before the second integration ships.
Overall. v5.1.0 is not a breaking change to the library's API, but it is a breaking change to its installability — the PHP floor moved from 8.1 to 8.2 in a minor release. That does not change the recommendation, but it sharpens it: gate on the runtime audit as well as the license, pin the version explicitly, and let the adapter absorb API drift while the pin absorbs platform drift. The PHP 8.5 support is a modestly encouraging maintenance signal. Still a reasonable, low-ceremony tool for a bounded problem — typed hydration of external JSON — provided legal clears the license and we wrap it behind our own interface. It is not a strategic bet: the low opportunity score and single-vendor maintenance argue for containment, not ubiquity. Approve for a scoped pilot pending the runtime audit, spike, and benchmark.
How can I help you explore Laravel packages today?