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

justinrainbow/json-schema

Validate JSON documents against JSON Schema in PHP. Supports Draft-3, Draft-4, Draft-6 and Draft-7 (coverage varies). Install via Composer and use JsonSchema\Validator to validate data with local file $ref schemas and inspect validation errors.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require justinrainbow/json-schema
    

    Add to composer.json if using Laravel's autoloader:

    "autoload": {
        "psr-4": {
            "App\\": "app/",
            "JsonSchema\\": "vendor/justinrainbow/json-schema/src/"
        }
    }
    
  2. First Use Case: Validate an incoming request payload against a schema in a Laravel controller:

    use JsonSchema\Validator;
    
    public function store(Request $request)
    {
        $validator = new Validator();
        $validator->validate($request->all(), (object) [
            "type" => "object",
            "properties" => (object) [
                "name" => (object) ["type" => "string"],
                "email" => (object) ["type" => "string", "format" => "email"]
            ],
            "required" => ["name", "email"]
        ]);
    
        if (!$validator->isValid()) {
            return response()->json(['errors' => $validator->getErrors()], 400);
        }
        // Proceed with logic
    }
    
  3. Where to Look First:


Implementation Patterns

Common Workflows

1. Request Validation

Pattern: Validate incoming API requests with automatic type coercion and default values.

use JsonSchema\Validator;
use JsonSchema\Constraints\Constraint;

public function update(Request $request)
{
    $validator = new Validator();
    $validator->coerce($request->all(), (object) [
        "type" => "object",
        "properties" => (object) [
            "active" => (object) ["type" => "boolean", "default" => false],
            "price" => (object) ["type" => "number", "minimum" => 0]
        ]
    ]);

    if (!$validator->isValid()) {
        return response()->json(['errors' => $validator->getErrors()], 400);
    }

    // $request->all() now has coerced types and defaults applied
}

2. Schema Storage for Reusable Schemas

Pattern: Centralize schema definitions for reuse across controllers.

// app/Providers/AppServiceProvider.php
public function boot()
{
    $schemaStorage = new \JsonSchema\SchemaStorage();
    $schemaStorage->addSchema('user', (object) [
        "type" => "object",
        "properties" => (object) [
            "name" => (object) ["type" => "string"],
            "email" => (object) ["type" => "string", "format" => "email"]
        ]
    ]);

    app()->singleton('schemaStorage', fn() => $schemaStorage);
}

// In a controller:
$validator = new Validator(new \JsonSchema\Constraints\Factory(app('schemaStorage')));
$validator->validate($data, (object) ["$ref" => "user"]);

3. Form Request Validation

Pattern: Extend Laravel's FormRequest for schema validation.

use JsonSchema\Validator;
use Illuminate\Foundation\Http\FormRequest;

class StoreUserRequest extends FormRequest
{
    public function validateSchema()
    {
        $validator = new Validator();
        $validator->validate($this->all(), (object) [
            "type" => "object",
            "properties" => (object) [
                "name" => (object) ["type" => "string", "minLength" => 3],
                "age" => (object) ["type" => "integer", "minimum" => 18]
            ]
        ]);

        if (!$validator->isValid()) {
            throw new \Exception("Validation failed: " . implode(", ", $validator->getErrors()));
        }
    }
}

4. Dynamic Schema Generation

Pattern: Generate schemas dynamically from Eloquent models.

use JsonSchema\Generator\ObjectGenerator;

public function getSchemaForModel($model)
{
    $generator = new ObjectGenerator();
    $schema = $generator->generate((object) [
        "type" => "object",
        "properties" => (object) array_map(fn($field) => (object) [
            "type" => $this->getTypeForField($field),
            "description" => $field->getComment()
        ], $model->getFillable())
    ]);

    return $schema;
}

5. Error Handling Middleware

Pattern: Centralize validation error responses.

// app/Http/Middleware/ValidateJsonSchema.php
public function handle($request, Closure $next)
{
    $validator = new Validator();
    $validator->validate($request->all(), $request->schema);

    if (!$validator->isValid()) {
        return response()->json([
            'errors' => $validator->getErrors(),
            'status' => 'validation_failed'
        ], 400);
    }

    return $next($request);
}

Integration Tips

  1. Laravel Service Container: Bind the validator with default configurations:

    $app->bind(Validator::class, fn() => new Validator(
        new \JsonSchema\Constraints\Factory(),
        Constraint::CHECK_MODE_COERCE_TYPES | Constraint::CHECK_MODE_APPLY_DEFAULTS
    ));
    
  2. API Resources: Validate responses before returning:

    public function toArray($request)
    {
        $validator = app(Validator::class);
        $validator->validate($this->resource, (object) [
            "type" => "object",
            "properties" => (object) [
                "id" => (object) ["type" => "integer"],
                "name" => (object) ["type" => "string"]
            ]
        ]);
    
        if (!$validator->isValid()) {
            throw new \Exception("Resource validation failed");
        }
    
        return $this->resource;
    }
    
  3. Testing: Use the validator in PHPUnit tests:

    public function testUserValidation()
    {
        $validator = new Validator();
        $validator->validate(['name' => 'John'], (object) [
            "type" => "object",
            "properties" => (object) ["name" => (object) ["type" => "string"]]
        ]);
    
        $this->assertTrue($validator->isValid());
    }
    
  4. Caching Schemas: Cache compiled schemas for performance:

    $schemaCache = Cache::remember('user_schema', 60, fn() => (object) [
        "type" => "object",
        "properties" => (object) [
            "name" => (object) ["type" => "string"],
            "email" => (object) ["type" => "string", "format" => "email"]
        ]
    ]);
    
    $validator->validate($data, $schemaCache);
    

Gotchas and Tips

Pitfalls

  1. Type Coercion Side Effects:

    • Issue: CHECK_MODE_COERCE_TYPES modifies the input data. Strings like "1" become integers.
    • Fix: Clone the input before coercion:
      $validator->coerce(clone $request->all(), $schema);
      
  2. Reference Resolution:

    • Issue: $ref paths with # (fragment identifiers) must be URL-encoded in file schemas.
    • Fix: Use file:///path/to/schema#/definitions/name (note triple slashes for Windows).
  3. Draft Incompatibility:

    • Issue: Draft-7 features (e.g., contains, prefixItems) may not be fully supported.
    • Fix: Check Bowtie Report for compliance before using newer drafts.
  4. Default Values Overwrite:

    • Issue: CHECK_MODE_APPLY_DEFAULTS overwrites null values, not just missing ones.
    • Fix: Use CHECK_MODE_ONLY_REQUIRED_DEFAULTS to avoid unintended overrides.
  5. Circular References:

    • Issue: Complex schemas with circular $refs may cause infinite loops.
    • Fix: Limit recursion depth or simplify schema structure.
  6. Format Validation:

    • Issue: Custom formats (e.g., date-time) require additional libraries (e.g., respect/validation).
    • Fix: Disable format checks with CHECK_MODE_DISABLE_FORMAT or implement custom validators.
  7. Large Schemas:

    • Issue: Memory issues with deeply nested or large schemas.
    • Fix: Use SchemaStorage to load schemas incrementally.

Debugging Tips

  1. Verbose Errors:
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.
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
ecotone/kafka
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata