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 Streamer Laravel Package

symfony/json-streamer

Symfony JsonStreamer provides powerful methods to read and write data structures from and into JSON streams, enabling memory-efficient processing of large JSON documents without loading everything at once.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture Fit

  • Use Case Alignment:
    • Perfect fit for Laravel applications handling large JSON payloads (API exports, ETL pipelines, real-time data streams).
    • Memory-efficient alternative to json_encode()/json_decode() for payloads >10MB, mitigating PHP’s default memory limits.
    • Streaming paradigm aligns with Laravel’s StreamedResponse, Queue Workers, and Artisan CLI tools for incremental processing.
  • Symfony Ecosystem Synergy:
    • Leverages Symfony’s Serializer component (already used in Laravel for form/data transformation), reducing duplication.
    • Complements Laravel’s HTTP layer (chunked responses) and background processing (queues).
  • Maturity Signal (new in v8.1.9):
    • The package has moved from the v8.1.0-BETA3 baseline used in the prior assessment to a stable 8.1.x patch line (v8.1.9) — nine patch releases, no breaking changes, no deprecations.
    • The v8.1.9 fix (#66744, Keep streamable resources for compiler passes that run after StreamablePass) confirms the package now participates in Symfony’s DI container compilation, not just runtime serialization. That is the correct architecture for Laravel (compiled container, config:cache, Octane preloading), but it moves part of the risk surface from “runtime serialization” into “container build / deployment”.
  • Performance Characteristics:
    • O(1) memory for streaming vs. O(n) for synchronous JSON.
    • Non-blocking I/O: ideal for long-running CLI/queue processes.

Integration Feasibility

  • Laravel-Specific Leverage:
    • HTTP: integrates with StreamedResponse for chunked JSON APIs (paginated exports).
    • Serialization: extends Laravel’s Serializer binding to support JsonStreamer for complex object graphs.
    • Queues: replaces json_decode() in jobs with incremental parsing (1GB JSON files).
    • CLI: enables memory-safe Artisan commands for data migration (php artisan import:json).
    • Container: compiler-pass integration (v8.1.9) means registration happens at build time — compatible with php artisan optimize, config:cache, and Octane’s container preload.
  • Dependency Footprint:
    • symfony/serializer (v6.0+ for Laravel 10+; v5.4+ for Laravel 9) and symfony/property-access (bundled in Laravel 10+).
    • No new transitive dependencies introduced by v8.1.9.
  • Upgrade Path from Prior Assessment:
    • Moving from 8.1.0-BETA3 → ^8.1.9 is a drop-in constraint bump; no API changes, no config changes, no migration scripts.
    • Required action is procedural, not code: clear and rebuild the compiled container (php artisan optimize:clear then optimize) so the corrected compiler pass ordering takes effect.

Technical Risk

  • Resource / Compiler-Pass Interaction (primary new item):
    • v8.1.9 deliberately retains streamable resources across compiler passes that execute after StreamablePass. This is the correct fix, but it means resources can outlive the pass that created them during container compilation.
    • Monitor: container build time and peak memory on composer install/artisan optimize in CI — a regression here indicates a resource not being released between passes.
    • Validate: full php artisan optimize:clear && php artisan optimize cycle on a clean checkout, plus an Octane boot/octane:reload cycle.
  • Long-Running Process Handle Leakage:
    • Because streamable resources are now held across passes, the analogous runtime concern is stream handles surviving beyond a request/job. Explicitly close/unset streams in finally blocks under Octane and queue workers; monitor open file descriptors (lsof -p <pid>) during soak tests.
  • Memory Leaks (carried over, now lower risk):
    • Previously mitigated fixes (stream reader/writer caching in v7.4.4+/v8.0.4+, resource growth in v7.3.10+) are all contained in the 8.1.x line.
    • Still test self-referencing objects (recursive JSON) to confirm the missing generator fixes hold.
  • PHP Version:
    • Requires PHP 8.1+ (Symfony 7.x) or 8.4+ (Symfony 8.x). Laravel 10+ defaults to PHP 8.2+, so risk is contained. Use Symfony 7.x for Laravel 9.
  • Complex Object Graphs:
    • Custom value transformers or synthetic properties may need adjustments for Eloquent; test nested hasMany/belongsTo with include_null_properties and union types.
  • Real-Time Use Cases:
    • WebSocket/event-driven streaming still needs custom emitters; extend JsonStreamer to Laravel Broadcast channels.

Key Questions

  1. Compiler-Pass Behaviour in Laravel’s Container:
    • Does StreamablePass run predictably inside Laravel’s container compilation order (which differs from a vanilla Symfony Kernel), and does the v8.1.9 retention behaviour hold when third-party packages register passes after it?
    • Action: Install alongside a representative pass-registering package (e.g., a large Laravel domain package) and diff php artisan optimize output/compile time before and after.
  2. Performance Benchmarks:
    • How does JsonStreamer compare to json_encode()/ijson for 100MB–1GB payloads on the 8.1.x stable line (previously benchmarked against BETA3)?
    • Action: Re-run the Phase 1 PoC benchmark on ^8.1.9 to confirm BETA-era numbers still hold.
  3. Laravel ORM Compatibility:
    • Does JsonStreamer correctly handle Eloquent accessors/mutators, casts, and hidden attributes?
    • Action: Test with a sample User model and nested Post relationships.
  4. Caching Strategy:
    • Partially answered by v8.1.9: the compiler-pass fix directly addresses streamable-resource loss during cached container builds (the risk flagged in the prior assessment’s Key Question #4).
    • Remaining: confirm no stale-container edge cases on deploy when only the JsonStreamer config changes.
    • Action: Add a deploy step that forces container rebuild on package version change; monitor build-time memory in CI.
  5. Error Handling:
    • How does JsonStreamer manage malformed JSON or partial streams (network interruptions)?
    • Action: Fuzz inputs and simulate StreamedResponse failures.
  6. Real-Time APIs:
    • Can JsonStreamer integrate with Laravel Broadcast for incremental WebSocket pushes?
    • Action: Prototype with Pusher/Echo and measure latency.

Integration Approach

Stack Fit

  • Laravel Integration Points:
    • HTTP Layer — StreamedResponse for chunked JSON APIs (/exports/large-report):
      use Symfony\Component\Serializer\JsonStreamer;
      use Illuminate\Http\StreamedResponse;
      
      return new StreamedResponse(
          fn() => (new JsonStreamer())->write($data, $response->getEmitter()),
          200,
          ['Content-Type' => 'application/json']
      );
      
    • Serializer — extend Laravel’s Serializer binding:
      $serializer = app(\Symfony\Component\Serializer\Serializer::class);
      $streamer = new JsonStreamer($serializer);
      $streamer->write($eloquentCollection, $response->getEmitter());
      
    • Queue Workers — replace synchronous json_decode() with incremental parsing:
      $streamer->read($filePath, function ($chunk) {
          // Process chunk (e.g., save to DB)
      });
      
    • Artisan Commands — CLI ETL / data migration:
      $streamer = new JsonStreamer();
      $streamer->read($file, function ($data) {
          DB::table('reports')->insert($data);
      });
      
    • Container / Deployment — new in scope as of v8.1.9: the package contributes a compiler pass, so it is exercised during artisan optimize and Octane preload. Treat container compilation as an integration surface, not just a black box.
    • Broadcasting — still experimental; requires a custom emitter.
  • Dependency Constraints:
    "require": {
        "symfony/serializer": "^6.0",
        "symfony/json-streamer": "^8.1.9"
    }
    
    Pin ^8.1.9 (or later 8.1.x) rather than any BETA constraint.

Migration Path

  1. Phase 0: Constraint & Cache Reset (new, ~30 min)

    • Bump symfony/json-streamer from the 8.1.0-BETA3 constraint to ^8.1.9.
    • Run composer update symfony/json-streamer and inspect for no unexpected transitive bumps.
    • Mandatory: php artisan optimize:clear, then php artisan optimize. Confirm the container compiles cleanly and note build time/memory as a baseline.
    • If Octane is in use: php artisan octane:reload and verify workers boot.
  2. Phase 1: Proof of Concept

    • Goal: Validate memory/performance gains for a single 50MB–100MB payload on the stable line.
    • Replace json_encode() in a test controller with StreamedResponse.
    • Success metrics: <30% memory usage vs. synchronous JSON; no timeouts for >100MB payloads; container compile time within ~5% of Phase 0 baseline.
  3. Phase 2: API Integration

    • Wrap JsonStreamer in a JsonStreamerService and roll it out controller-by-controller.
    • Add a CI guard that fails the build if php artisan optimize exceeds the Phase 0 memory baseline (catches compiler-pass resource regressions early).
  4. Phase 3: Async & CLI

    • Adopt in queue jobs and Artisan ETL commands; ensure streams are closed in finally blocks.
  5. Phase 4: Real-Time (optional / experimental)

    • Prototype broadcasting integration; keep behind a feature flag.

Operational Impact

Maintenance

  • Low-to-moderate cadence: nine patch releases between v8.1.0-BETA3 and v8.1.9, all backward compatible. Expect routine composer update hygiene rather than migration work.
  • Stay within the 8.1.x line; treat 8.2 as a planned minor upgrade with a full container-rebuild validation pass.
  • Track releases that touch compiler passes specifically — they carry deployment risk even when semantically minor.

Support

  • Upstream is the Symfony organisation, with a published security/LTS policy and an active issue tracker; this is materially stronger support than a typical single-maintainer Laravel package.
  • Internal support burden is low: the API surface used by Laravel teams (read/write + emitter) is small. Internal runbook should document the container-rebuild step as the first troubleshooting action for any streaming-related post-deploy anomaly.

Scaling

  • Scales horizontally without change to app servers: streaming is per-request and memory-bounded.
  • File-descriptor budget is the scaling limit, not heap: with resources retained by the compiler pass and open during request lifetimes, size ulimit -n and PHP-FPM/Octane worker counts accordingly.
  • Long-running workers (queues, Octane) scale linearly provided handles are explicitly released; without that discipline, fd exhaustion appears as intermittent 500s under sustained load rather than at ramp.

Failure Modes

Mode Trigger Signal Mitigation
Container compile failure Pass ordering conflict with a third-party bundle artisan optimize fatal at deploy Pin ^8.1.9; validate in CI with representative packages installed
Stale compiled container Deploy without cache clear after version bump Streamer behaves per pre-fix semantics Force optimize:clear on package version change
Resource/fd exhaustion Handles not closed in Octane/queue workers Sporadic 500s under load; rising lsof fd count try/finally stream closure; soak test
Stream resource retention during build New v8.1.9 behaviour under many passes CI build memory/time drift Baseline + threshold gate in CI
Malformed/partial JSON Network interruption, fuzzed input Truncated payloads, unhandled exceptions Explicit error handling around read()
Memory regression Deeply nested / recursive object graphs Memory ceiling reached Regression fixtures; monitor the leak-fix areas
Eloquent serialization mismatch Casts, accessors, hidden attributes Wrong payload shape Contract tests on representative models

Ramp-Up

  • Engineering effort: low (~1 day). The read/write API is a two-method surface; a Laravel developer can be productive in under a day, and the existing Serializer familiarity transfers directly.
  • Additional ramp for deployment/DevOps: ~half a day. The genuinely new knowledge from v8.1.9 is that this package participates in container compilation — the on-call runbook, CI pipeline, and deploy checklist must reflect that.
  • Recommended enablement: one engineer owns the Phase 0/1 validation, produces the benchmark and container-build baselines, and writes the runbook entry. This is a small, well-bounded ramp with no framework-level retraining required.
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.
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource