Weave Code
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 Path Laravel Package

symfony/json-path

Evaluate JSONPath expressions in Symfony/PHP to query and extract data from JSON documents. Lightweight library with simple API for selecting nodes, filtering arrays, and retrieving values, useful for config parsing, API responses, and data transformation.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation

    composer require symfony/json-path
    

    No additional configuration is required—autoloading handles the rest.

  2. First Use Case: Extracting Nested Data

    use Symfony\Component\JsonPath\JsonPath;
    
    $json = '{"user": {"profile": {"name": "John", "age": 30}}}';
    $jsonPath = new JsonPath();
    $name = $jsonPath->evaluate('$.user.profile.name', json_decode($json, true));
    // Returns: "John"
    
  3. Where to Look First

    • RFC 9535: JSONPath Specification for syntax rules.
    • Core Methods:
      • evaluate(): Single result (or null).
      • evaluateAll(): Array of all matches.
      • search(): Alias for evaluate() (Symfony-compatible).
    • Laravel Integration: Pair with json_decode() or Laravel’s Http client for API responses.

Implementation Patterns

Usage Patterns

  1. API Response Parsing

    public function parseStripeResponse($response)
    {
        $data = json_decode($response->getBody(), true);
        $amount = JsonPath::search($data, '$.data.object.amount');
        $currency = JsonPath::search($data, '$.data.object.currency');
        return [$amount, $currency];
    }
    
  2. Dynamic Query Building

    public function getNestedValue($json, string $path, $default = null)
    {
        return JsonPath::search($json, $path) ?? $default;
    }
    // Usage:
    $age = $this->getNestedValue($userJson, '$.user.profile.age', 0);
    
  3. Filtering with Predicates

    $expensiveItems = JsonPath::search($inventory, '$.items[?(@.price > 100)].name');
    // Returns: ["Laptop", "Monitor"]
    
  4. Laravel Service Container Binding

    // app/Providers/AppServiceProvider.php
    public function register()
    {
        $this->app->bind(JsonPath::class, fn() => new JsonPath());
    }
    // Usage in controllers:
    public function __construct(private JsonPath $jsonPath) {}
    
  5. Validation Helper

    public function validateRequiredFields($json, array $paths)
    {
        foreach ($paths as $path) {
            if (empty(JsonPath::search($json, $path))) {
                throw new \InvalidArgumentException("Missing required path: $path");
            }
        }
    }
    

Workflow Integration

  • Middleware for API Responses:

    public function handle($request, Closure $next)
    {
        $response = $next($request);
        if ($response->isOk()) {
            $data = json_decode($response->getBody(), true);
            $response->setData(JsonPath::search($data, '$.transformed.path'));
        }
        return $response;
    }
    
  • Eloquent JSON Casting:

    use Illuminate\Database\Eloquent\Casts\Attribute;
    
    public function transformedJson(): Attribute
    {
        return Attribute::make(
            get: fn($value) => JsonPath::search($value, '$.user.profile.name'),
        );
    }
    
  • Artisan Commands for Data Extraction:

    public function handle()
    {
        $json = file_get_contents('data.json');
        $results = JsonPath::searchAll($json, '$.records[*].id');
        $this->line('Extracted IDs: ' . implode(', ', $results));
    }
    

Gotchas and Tips

Pitfalls

  1. Path Evaluation Quirks

    • Issue: $.store..book (recursive descent) may not work as expected in all JSON structures.
    • Fix: Use evaluateAll() and filter results manually if needed:
      $allBooks = JsonPath::searchAll($json, '$.store.*[*].book');
      
  2. Case Sensitivity in Keys

    • Issue: $.User.Name fails if the JSON uses $.user.name.
    • Fix: Normalize keys or use case-insensitive JSON parsers like json_decode($json, true, 512, JSON_BIGINT_AS_STRING).
  3. Performance with Deep Nesting

    • Issue: Complex paths (e.g., $.a.b.c.d[*].e) can slow down evaluation.
    • Fix: Cache parsed JSON or use evaluateAll() for bulk operations.
  4. False Matches with Wildcards

    • Issue: *.book matches any object with a book key, not just top-level objects.
    • Fix: Anchor paths explicitly (e.g., $.store.book).
  5. Empty Results vs. null

    • Issue: evaluate() returns null for missing paths, while evaluateAll() returns an empty array.
    • Fix: Use empty() checks for evaluateAll() and is_null() for evaluate().

Debugging Tips

  • Log Path Evaluations:

    try {
        $result = JsonPath::search($json, $path);
        Log::debug("Path [$path] resolved to: ", ['result' => $result]);
    } catch (\Symfony\Component\JsonPath\Exception\JsonPathException $e) {
        Log::error("Invalid JSONPath [$path]: " . $e->getMessage());
    }
    
  • Validate JSON First:

    if (json_validate($json)) {
        $result = JsonPath::search($json, $path);
    } else {
        throw new \InvalidArgumentException("Invalid JSON provided");
    }
    
  • Test Edge Cases:

    // Test empty JSON
    $this->assertNull(JsonPath::search([], '$.nonexistent'));
    
    // Test arrays
    $this->assertEquals([1, 2], JsonPath::search([1, 2], '$[*]'));
    
    // Test nested arrays
    $this->assertEquals([1, 2], JsonPath::search([['a', 1], ['b', 2]], '$[*][1]'));
    

Extension Points

  1. Custom JSONPath Functions

    • Issue: Need custom functions (e.g., contains()).
    • Workaround: Pre-process JSON with Laravel Collections or use a wrapper:
      $filtered = collect($json)->filter(fn($item) => str_contains($item, 'search'));
      
  2. Laravel Facade

    • Tip: Create a facade for cleaner syntax:
      // app/Facades/JsonPath.php
      namespace App\Facades;
      use Illuminate\Support\Facades\Facade;
      class JsonPath extends Facade { protected static function getFacadeAccessor() => 'jsonPath'; }
      
      Register in AppServiceProvider:
      $this->app->bind('jsonPath', fn() => new \Symfony\Component\JsonPath\JsonPath());
      
      Usage:
      $result = \App\Facades\JsonPath::search($json, '$.path');
      
  3. Performance Optimization

    • Tip: Cache parsed JSON for repeated queries:
      $cacheKey = md5($json . $path);
      return Cache::remember($cacheKey, now()->addMinutes(10), fn() =>
          JsonPath::search($json, $path)
      );
      
  4. Integration with Laravel HTTP Client

    • Tip: Add a macro to Laravel’s Http client:
      // app/Providers/AppServiceProvider.php
      use Illuminate\Support\Facades\Http;
      Http::macro('jsonPath', function ($path) {
          return JsonPath::search($this->json(), $path);
      });
      
      Usage:
      $response = Http::get('https://api.example.com/data')->jsonPath('$.data.id');
      
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.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky