jane-php/json-schema-runtime
Runtime support library for code generated by Jane JsonSchema. Provides shared classes used by Jane-generated PHP clients and models (serialization, validation, etc.). See Jane docs for usage and contribute via the main janephp repository.
Install the Package:
composer require jane-php/json-schema-runtime
Ensure your project uses PHP 8.1+ (check php -v).
Define a Schema:
Create a JSON/YAML schema file (e.g., schemas/user.json):
{
"type": "object",
"properties": {
"name": { "type": "string" },
"email": { "type": "string", "format": "email" }
},
"required": ["name", "email"]
}
First Validation:
use Jane\JsonSchemaRuntime\Validator;
$validator = new Validator();
$schema = json_decode(file_get_contents('schemas/user.json'), true);
$data = ['name' => 'John', 'email' => 'john@example.com'];
$isValid = $validator->validate($data, $schema);
// Returns `true` if valid, throws `Jane\JsonSchemaRuntime\Exception\RuntimeException` if invalid.
Laravel Integration:
Register the validator in AppServiceProvider:
public function register() {
$this->app->singleton(Validator::class);
}
Use middleware to validate incoming API requests:
// app/Http/Middleware/ValidateSchema.php
public function handle(Request $request, Closure $next) {
$validator = app(Validator::class);
$schema = json_decode(file_get_contents("schemas/{$request->route()->getName()}.json"), true);
if (!$validator->validate($request->all(), $schema)) {
return response()->json(['error' => 'Validation failed'], 422);
}
return $next($request);
}
Register in app/Http/Kernel.php:
protected $middleware = [
\App\Http\Middleware\ValidateSchema::class,
];
Extend FormRequest to validate against a schema:
use Jane\JsonSchemaRuntime\Validator;
class StoreUserRequest extends FormRequest {
public function authorize() {
return true;
}
public function rules() {
return [];
}
public function validateSchema() {
$validator = app(Validator::class);
$schema = json_decode(file_get_contents('schemas/user.json'), true);
$validator->validate($this->all(), $schema);
}
}
Validate API responses before sending:
// app/Http/Controllers/UserController.php
public function show(User $user) {
$responseData = $user->toArray();
$validator = app(Validator::class);
$schema = json_decode(file_get_contents('schemas/user-response.json'), true);
if (!$validator->validate($responseData, $schema)) {
abort(500, 'Internal validation error');
}
return response()->json($responseData);
}
Load schemas dynamically from a database or config:
public function validateWithDynamicSchema(array $data, string $schemaKey) {
$validator = app(Validator::class);
$schema = config("schemas.{$schemaKey}"); // Load from config
return $validator->validate($data, $schema);
}
Leverage Laravel’s Service Container: Bind the validator as a singleton to avoid reinstantiation:
$this->app->singleton(Validator::class, fn() => new Validator());
Combine with Laravel Validation: Use Jane’s validator for complex nested structures and Laravel’s validator for simple rules:
$validator = Validator::make($request->all(), [
'name' => 'required|string',
'email' => 'required|email',
]);
if ($validator->fails()) {
return response()->json(['errors' => $validator->errors()], 422);
}
// Additional schema validation
$schemaValidator = app(Validator::class);
$schema = json_decode(file_get_contents('schemas/user.json'), true);
$schemaValidator->validate($request->all(), $schema);
Schema Generation with Jane JsonSchema: If using Jane JsonSchema, generate schemas from PHP classes and validate at runtime:
// Generate schema from a PHP class
$generator = new \Jane\JsonSchemaGenerator\Generator();
$schema = $generator->generate(new \stdClass(), 'User');
// Validate runtime data
$validator = new Validator();
$validator->validate($data, $schema);
Error Handling: Catch validation exceptions and return user-friendly errors:
try {
$validator->validate($data, $schema);
} catch (\Jane\JsonSchemaRuntime\Exception\RuntimeException $e) {
return response()->json([
'errors' => $e->getMessage(),
'details' => $e->getErrors(),
], 422);
}
Testing: Write tests to ensure schemas are enforced:
public function test_user_schema_validation() {
$validator = new Validator();
$schema = json_decode(file_get_contents('schemas/user.json'), true);
// Valid data
$this->assertTrue($validator->validate(['name' => 'John', 'email' => 'john@example.com'], $schema));
// Invalid data
$this->expectException(\Jane\JsonSchemaRuntime\Exception\RuntimeException::class);
$validator->validate(['name' => 123], $schema);
}
No Detailed Error Messages by Default:
The validator throws a generic RuntimeException on failure. Extract errors manually:
try {
$validator->validate($data, $schema);
} catch (\Jane\JsonSchemaRuntime\Exception\RuntimeException $e) {
$errors = $e->getErrors(); // Array of error details
}
PHP 8.1+ Requirement:
The package requires PHP 8.1+. If your project uses an older version, consider alternatives like justinrainbow/json-schema.
Stale Maintenance:
The package hasn’t been updated since 2018. Monitor for forks or alternatives (e.g., symfony/validator). Consider forking to backport fixes.
Dependency Conflicts:
league/uri v6/7 may conflict with Laravel’s symfony/routing. Test thoroughly.symfony/serializer v8.x may require Laravel 10+.Schema Complexity: Overly complex schemas can lead to performance issues. Keep schemas simple and test under load.
No Dynamic Schema Updates: Schemas must be predefined. Avoid runtime schema modifications.
Enable Detailed Errors: Extend the validator to log detailed errors:
$validator = new Validator();
$validator->setErrorFormatter(function ($errors) {
return json_encode($errors, JSON_PRETTY_PRINT);
});
Validate Schema Syntax: Use an online JSON/YAML validator to ensure schemas are syntactically correct before runtime.
Check for Deprecated Features:
The package may use deprecated PHP features. Test with php -l (lint) and phpstan for static analysis.
Isolate Validation Logic: Test schemas in isolation before integrating into Laravel:
$validator = new Validator();
$schema = json_decode(file_get_contents('schemas/test.json'), true);
$this->assertTrue($validator->validate(['key' => 'value'], $schema));
Custom Error Handling: Override the default exception handler:
$validator = new Validator();
$validator->setExceptionHandler(function ($errors) {
throw new \RuntimeException('Custom error: ' . json_encode($errors));
});
Schema Caching: Cache compiled schemas to improve performance:
$cache = new \Symfony\Component\Cache\SimpleFileCache();
$schema = $cache->get('user_schema', function() use ($validator) {
return json_decode(file_get_contents('schemas/user.json'), true);
});
Integration with Laravel Events:
Validate data in Illuminate\Queue\Jobs\Job or Illuminate\Bus\Queueable:
public function handle() {
$validator = app(Validator::class);
$schema = json_decode(file_get_contents('schemas/job-payload.json'), true);
if (!$validator->validate($this->data, $schema)) {
throw new \Exception('Invalid job payload');
}
// Process job
}
GraphQL Validation: Use with `webonyx
How can I help you explore Laravel packages today?