Installation Add the package via Composer:
composer require laravel-json-api/spec
Publish the config (if needed):
php artisan vendor:publish --provider="LaravelJsonApi\Spec\JsonApiServiceProvider"
First Use Case: Validating a JSON:API Response
Use the JsonApiValidator facade to validate a JSON:API-compliant response:
use LaravelJsonApi\Spec\JsonApiValidator;
$response = [
'data' => [
'type' => 'posts',
'id' => '1',
'attributes' => ['title' => 'Hello World'],
'relationships' => [
'author' => ['data' => ['type' => 'users', 'id' => '1']]
]
]
];
$validator = JsonApiValidator::make($response);
if ($validator->fails()) {
// Handle validation errors
dd($validator->errors());
}
Where to Look First
tests/ for edge cases.config/json-api.php (if published) for custom rules.Request Validation
Validate incoming JSON:API requests (e.g., POST /posts):
use LaravelJsonApi\Spec\JsonApiValidator;
use Illuminate\Http\Request;
public function store(Request $request)
{
$validator = JsonApiValidator::make($request->json()->all());
if ($validator->fails()) {
return response()->json(['errors' => $validator->errors()], 422);
}
// Proceed with logic...
}
Response Validation Ensure API responses comply before sending:
public function show($id)
{
$post = Post::findOrFail($id);
$response = [
'data' => [
'type' => 'posts',
'id' => $post->id,
'attributes' => $post->toArray(),
]
];
$validator = JsonApiValidator::make($response);
if ($validator->fails()) {
abort(500, 'Invalid JSON:API response');
}
return response()->json($response);
}
Custom Rules Extend validation with custom rules (e.g., for nested relationships):
use LaravelJsonApi\Spec\Rules\RelationshipRule;
$validator = JsonApiValidator::make($data)
->withRules([
'data.relationships.author.data' => new RelationshipRule(['type' => 'required', 'id' => 'required']),
]);
FormRequest for API-specific validation:
use LaravelJsonApi\Spec\JsonApiValidator;
use Illuminate\Foundation\Http\FormRequest;
class StorePostRequest extends FormRequest
{
public function validateJsonApi()
{
$validator = JsonApiValidator::make($this->json()->all());
if ($validator->fails()) {
throw new \Illuminate\Validation\ValidationException($validator->errors());
}
}
}
namespace App\Http\Middleware;
use Closure;
use LaravelJsonApi\Spec\JsonApiValidator;
class ValidateJsonApi
{
public function handle($request, Closure $next)
{
$validator = JsonApiValidator::make($request->json()->all());
if ($validator->fails()) {
return response()->json(['errors' => $validator->errors()], 422);
}
return $next($request);
}
}
Strict vs. Lenient Validation
meta if not required).->lenient() to skip non-critical checks:
JsonApiValidator::make($data)->lenient();
Nested Relationships
data objects in relationships:
// Valid
"relationships": {
"author": { "data": { "type": "users", "id": "1" } }
}
// Invalid (missing `data` wrapper)
"relationships": {
"author": { "type": "users", "id": "1" }
}
ID/Type Requirements
id and type are required for all resource objects (data, relationships, etc.).->withRules([
'data.id' => 'required|string',
'data.type' => 'required|string|in:posts,users',
]);
Pagination Conflicts
links (not meta):
// Valid
"links": {
"next": "/posts?page=2"
}
// Invalid (unless lenient)
"meta": { "pagination": { "next": "/posts?page=2" } }
->errors() to inspect failures:
$validator->fails(); // bool
$validator->errors(); // array of error messages
\Log::error('JSON:API Validation Failed', ['errors' => $validator->errors()]);
data arrays.type/id in nested objects.Custom Rules
Extend LaravelJsonApi\Spec\Rules\BaseRule for domain-specific logic:
use LaravelJsonApi\Spec\Rules\BaseRule;
class CustomRule extends BaseRule
{
public function passes($attribute, $value)
{
return str_contains($value['title'], 'Laravel');
}
}
Override Default Rules
Modify the validator’s default rules in config/json-api.php:
'rules' => [
'data' => [
'required',
'array',
'has' => ['type', 'id'],
],
'data.*.type' => 'required|string',
'data.*.id' => 'required|string',
],
Hook into Validation Use events to react to validation results:
JsonApiValidator::make($data)
->onFail(function ($validator) {
// Custom logic (e.g., log, transform errors)
});
How can I help you explore Laravel packages today?