Install the Package:
composer require jane-php/json-schema
composer require jane-php/json-schema-runtime # For runtime validation
Define a JSON Schema:
Create a schema file (e.g., config/schemas/user.schema.json):
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "User",
"type": "object",
"properties": {
"id": { "type": "integer" },
"name": { "type": "string" },
"email": { "type": "string", "format": "email" }
},
"required": ["id", "name"]
}
Generate PHP Model: Use the generator to create a class from the schema:
use Jane\JsonSchema\Generator;
$generator = new Generator();
$models = $generator->generateFromFile('config/schemas/user.schema.json');
file_put_contents('app/Models/Generated/User.php', $models->getCode());
Use the Generated Model: The generated class will include:
$id, $name, $email).JsonSerializable, Arrayable).jane-php/json-schema-runtime).Example usage:
use App\Models\Generated\User;
$userData = ['id' => 1, 'name' => 'John Doe', 'email' => 'john@example.com'];
$user = User::fromArray($userData); // Deserialize
$json = $user->toJson(); // Serialize
Integrate with Laravel:
FormRequest for validation:
use Jane\JsonSchemaRuntime\Validator\Validator;
public function rules()
{
return [
'data' => ['required', function ($attribute, $value, $fail) {
$schema = file_get_contents('config/schemas/user.schema.json');
if (!Validator::validate($value, $schema)) {
$fail('Invalid user data: ' . Validator::getErrors());
}
}]
];
}
Schema-Driven API Development:
config/schemas/ or version-controlled files.composer install or via a custom artisan command:
// app/Console/Commands/GenerateModels.php
use Jane\JsonSchema\Generator;
use Symfony\Component\Filesystem\Filesystem;
class GenerateModels extends Command
{
protected $signature = 'schema:generate';
protected $description = 'Generate models from all JSON schemas';
public function handle()
{
$fs = new Filesystem();
$generator = new Generator();
foreach (glob('config/schemas/*.schema.json') as $schemaFile) {
$models = $generator->generateFromFile($schemaFile);
$fs->dumpFile(
str_replace('schemas/', 'Models/Generated/', $schemaFile),
$models->getCode()
);
}
}
}
Validation Layer:
Validator with Jane’s runtime validator:
// app/Services/SchemaValidator.php
use Jane\JsonSchemaRuntime\Validator\Validator;
class SchemaValidator
{
public static function validate(array $data, string $schemaPath): bool
{
$schema = file_get_contents($schemaPath);
return Validator::validate($data, $schema);
}
}
FormRequest:
public function validateResolved()
{
if (!SchemaValidator::validate($this->input(), 'config/schemas/user.schema.json')) {
$this->fail(SchemaValidator::getErrors());
}
}
API Resources:
JsonResource:
// app/Http/Resources/UserResource.php
use App\Models\Generated\User;
use Illuminate\Http\Resources\Json\JsonResource;
class UserResource extends JsonResource
{
public function toArray($request)
{
return User::fromArray($this->resource)->toArray();
}
}
Custom Formats:
date format):
use Jane\JsonSchema\Format\Format;
Format::add('date', function ($value) {
return Carbon::parse($value)->format('Y-m-d');
});
Symfony Compatibility:
symfony/serializer for advanced serialization needs:
use Symfony\Component\Serializer\SerializerInterface;
$serializer = app(SerializerInterface::class);
$user = $serializer->deserialize($json, User::class, 'json');
Laravel Events:
// app/Providers/AppServiceProvider.php
use Symfony\Component\Filesystem\Filesystem;
public function boot()
{
if ($this->app->environment('local')) {
Storage::disk('local')->delete('app/Models/Generated');
$this->call('schema:generate');
}
}
Testing:
$mockUser = Mockery::mock(User::class);
$mockUser->shouldReceive('toArray')->andReturn(['id' => 1, 'name' => 'Test']);
Caching:
if (!file_exists('bootstrap/cache/generated_models.php')) {
$this->call('schema:generate');
file_put_contents('bootstrap/cache/generated_models.php', '<?php // Generated models');
}
Stale Code Generation:
Namespace Conflicts:
App\Models\Generated) and exclude from autoloading:
// composer.json
"autoload-exclude": ["app/Models/Generated/"]
Circular References:
$ref handling:
$generator->setMaxRefDepth(5);
Runtime Validation Overhead:
PHP 8.1+ Compatibility:
spatie/fork-jane-json-schema.Symfony Dependencies:
Carbon instead of symfony/options-resolver).Validation Errors:
Validator::setErrorFormatter(function ($errors) {
return json_encode($errors, JSON_PRETTY_PRINT);
});
Generation Failures:
$generator->setDebug(true);
Schema Parsing Issues:
Partial Generation:
php artisan schema:generate config/schemas/user.schema.json
Custom Traits:
// app/Models/Generated/User.php (after generation)
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable implements JsonSerializable
{
// Generated properties/methods
}
OpenAPI Integration:
zircote/swagger-php, then feed them to Jane:
$openApi = \OpenApi\Generator::scan(['app/Http/Controllers']);
$schema = $openApi->toJson();
file_put_contents('config/schemas/api.schema.json', $schema);
Performance Optimization:
php artisan optimize:clear
Schema Versioning:
How can I help you explore Laravel packages today?