PHPackages                             serhiikamolov/laravel-jsonapi - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. serhiikamolov/laravel-jsonapi

ActiveLibrary[API Development](/categories/api)

serhiikamolov/laravel-jsonapi
=============================

A set of interfaces and classes to facilitate the construction of an efficient Json Api application with the Laravel framework.

v4.2(1y ago)331.0k↓45.1%MITPHPPHP ^8.4

Since Jul 23Pushed 1y ago2 watchersCompare

[ Source](https://github.com/serhiikamolov/laravel-jsonapi)[ Packagist](https://packagist.org/packages/serhiikamolov/laravel-jsonapi)[ RSS](/packages/serhiikamolov-laravel-jsonapi/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (10)Dependencies (8)Versions (44)Used By (0)

Laravel JsonAPI
===============

[](#laravel-jsonapi)

A set of interfaces and classes to facilitate the construction of an efficient JSON:API application with the Laravel framework.

 [![Latest Stable Version](https://camo.githubusercontent.com/4d6257e30f03e550e021d058b69880f819cdde885fdb9f87072118cf98cd768d/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f7365726869696b616d6f6c6f762f6c61726176656c2d6a736f6e6170692e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/serhiikamolov/laravel-jsonapi) [![License](https://camo.githubusercontent.com/55c0218c8f8009f06ad4ddae837ddd05301481fcf0dff8e0ed9dadda8780713e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d627269676874677265656e2e7376673f7374796c653d666c61742d737175617265)](https://opensource.org/licenses/MIT)

#### Table of contents

[](#table-of-contents)

- [Installation](#installation)
- [Custom error handler](#custom-error-handler)
- [Request validation class](#request-validation-class)
- [Response class](#response-class)
- [Serializer class](#serializer-class)
    - [Declaring Serializers](#declaring-serializers)
    - [Using Model Serializers](#using-model-serializers)
    - [Using Field Modifiers](#using-field-modifiers)
- [Expand Response with the Queries Log](#expand-response-with-the-queries-log)
- [Testing API Responses](#testing-api-responses)

Installation
------------

[](#installation)

This package is very easy to set up via Composer, just run from your project's root folder:

```
composer require serhiikamolov/laravel-jsonapi
```

Custom error handler
--------------------

[](#custom-error-handler)

In order to make errors output compatible with json API format go to `bootstrap/app.php` and register the custom error handler.

```
$app->singleton(
   Illuminate\Contracts\Debug\ExceptionHandler::class,
   \JsonAPI\Exceptions\Handler::class
);
```

Or just extend default `App\Exceptions\Handler` from `JsonAPI\Exceptions\Handler` class.

Now, in case of an exception you will get such a response:

```
{
    "links": {
        "self": "http://127.0.0.1/api/v1/auth/login"
    },
    "errors": {
        "messages": [
            "Some internal exception"
        ]
    },
    "debug": {
        "message": "Some internal exception",
        "exception": "Exception",
        "file": "/code/app/Http/Controllers/AuthController.php",
        "line": 29,
        "trace": [...]
    }
}
```

Request validation class
------------------------

[](#request-validation-class)

`\JsonAPI\Contracts\Request` is a simple extension of the `FormRequest` class that returns the validation errors in compatible with the json API form

```
namespace App\Http\Requests\Auth;

use \JsonAPI\Contracts\Request;

class LoginRequest extends Request
{

    public function messages()
    {
        return [
            'email.required'  => 'Значення e-mail не може бути порожнім',
            'email.email'   => 'Значення e-mail не відповідає формату електронної пошти',
            'email.max'     => 'Значення e-mail не має бути таким довгим',
        ];
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules():array
    {
        return [
            'email' => 'required|email|max:255',
            'password' => 'required|string',
        ];
    }

}
```

Example of a controller with request validation:

```
namespace App\Http\Controllers;

use JsonAPI\Response\Response;
use App\Http\Requests\Auth\LoginRequest;

class AuthController extends Controller
{
    /**
     * Request a JWT token
     *
     * @param LoginRequest $request
     * @param Response $response
     * @return JsonResponse
     */
    public function login(LoginRequest $request, Response  $response):Response
    {
        // validation is passed, you can check the user credentials now
        // and generate a JWT token
    }
}
```

Response with validation errors:

```
{
    "links": {
        "self": "http://127.0.0.1/api/v1/auth/login"
    },
    "errors": {
        "email": [
            "The email field is required."
        ]
    }
}
```

Response class
--------------

[](#response-class)

`JsonAPI\Response\Response` is an exension of the `JsonResponse` class with some additional methods.

**Add additional values to the links object of the response**

```
$response->links($array)
```

**Return error with the specific code in the response**

```
$response->error($statusCode, $message)
```

**Return response with JWT token**

```
$response->token($token, $type = 'bearer', $expires = null)
```

**Return a custom data object in the response**

```
$response->data($array)
```

**Attach a field to the response's data object**

```
$response->attach($key, $value)
```

**Add a debug information to the response object**

```
$response->debug($array)
```

**Add a meta data to the response object**

```
$response->meta($array, $key = 'meta')
```

**Serialize an eloquent collection or a data model**

```
$response->serialize($collection, $serializer = new Serializer())
```

**Paginate a data array in the response**

```
$response->serialize($collection)->paginate()
```

**Add a specific status code to the response**

```
$response->code($statusCode)
```

`Response` class is an implementation of the Builder pattern thus you can use diffrent methods in a row:

```
public function login(LoginRequest $request, Response $response): Response
{
    ...
    return $response
        ->token((string)$token)
        ->attach('uuid', Auth::guard('api')->user()->uuid);
}
```

Response result:

```
{
    "links": {
        "self": "http://127.0.0.1/api/v1/auth/login"
    },
    "data": {
        "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC8xMjcuMC4wLjFcL2FwaVwvdjFcL2F1dGhcL2xvZ2luIiwiaWF0IjoxNjA4Mzc0NTAyLCJleHAiOjE2MDgzNzQ1NjIsIm5iZiI6MTYwODM3NDUwMiwianRpIjoiUXRZWnpUeEhYajJyaGxHaCIsInN1YiI6MiwicHJ2IjoiY2U2ZTY0NDI4OTkwYjk4NWJjZTQ2OGZjNTlmZTUxYzNiZTljN2ZhZCJ9.PNF2-5nswNqaWS4WS1D_gemBD3IyPJVKXJohNF8mMUY",
        "token_type": "bearer",
        "expires_in": 60,
        "uuid": "40e831349e594d8e944478a243ff463f"
    }
}
```

Serializer class
----------------

[](#serializer-class)

Serializers allow complex data such as Eloquent Collections and Model instances to be converted to a simple array that can be easily rendered into JSON. Serializer class gives you a powerful, generic way to control the output of your responses.

#### Declaring Serializers

[](#declaring-serializers)

Let's create a simple serializer class extended from the `JsonAPI\Response\Serializer` class. There is a public method `fields()` which returns an array, and define a set of fields which will be retrieved from the given Collection or Model and put to the response.

```
namespace App\Http\Serializers;

use JsonAPI\Response\Serializer;

class UserSerializer extends Serializer
{
    public function fields(): array
    {
        return [
            'id',    // take data from $user->id
            'name',  // take data from $user->name
            'email', // take data from $user->email
            'uuid'   // take data from the public method defined below
        ];
    }

    /**
    * Define a custom field
    */
    public function uuid(Model $item): string
    {
        return md5($item->id);
    }
}
```

Here you can notice that `uuid` is not taken from the database but generated from the model data. In such a way you can define any new field you need in the response or even override an existing field value.

#### Using Model Serializers

[](#using-model-serializers)

There is `serialize` method in the `JsonAPI\Response\Response` class which accept a Serializer instance as a second parameter.

```
class UsersController extends Controller
{
    /**
     * Get list of all users.
     *
     * @param Response $response
     * @return Response
     */
    public function read(Response $response): Response
    {
        $users = User::all();
        return $response->serialize($users, new UserSerializer());
    }
}
```

Response result

```
{
    "links": {
        "self": "http://127.0.0.1/api/v1/users"
    },
    "data": [
        {
            "id": 1,
            "name": "admin",
            "email": "user@email.com",
            "uuid": "40e831349e594d8e944478a243ff463f"
        }
    ]
}
```

#### Using Field Modifiers

[](#using-field-modifiers)

Field modifiers can be applied to every field defined in serializer. Although, there are a few predefined modifiers: `timestamp`, `number`, `trim`you can define your own modifier by creating a `protected` method with the `modifier` prefix in its name. Also you can use another serializing class as a modifier, it can be useful when you have some related data to the original model.

```
class UserSerializer extends Serializer
{
    public function fields(): array
    {
        return [
            'id' => 'md5'                       // use custom modifier
            ...
            'created_at' => 'timestamp',        // use default modifier which
                                                // transforms a Carbon date object
                                                // into the unix timestamp number
            'roles' => RoleSerializer::class    // use a serializing class as a modifier
                                                // for the related data
        ];
    }

     /**
     * Define custom modifier which transforms user id to md5 hash.
     * @param int|null $value
     * @return int
     */
    protected function modifierMd5(?int $value): string
    {
        return md5($value);
    }
}
```

Expand Response with the Queries Log
------------------------------------

[](#expand-response-with-the-queries-log)

Enable `JsonAPI\Http\Middleware\JsonApiDebug` middleware and expand the `debug` section of a response with the information from the queries log.

```
namespace App\Http;

use Illuminate\Foundation\Http\Kernel as HttpKernel;

class Kernel extends HttpKernel
{
    protected $middlewareGroups = [
        ...
        'api' => [
            ...
            \JsonAPI\Http\Middleware\JsonApiDebug::class
        ],
        ...
    ];
}
```

Response with the queries log.

```
{
  ...
  "debug": {
    "queries": {
        "total": 2,
        "list": [
            {
                "query": "select * from `users` where `id` = ? limit 1",
                "bindings": [
                    2
                ],
                "time": 20.81
            },
            {
                "query": "select `roles`.*, `role_user`.`user_id` as `pivot_user_id`, `role_user`.`role_id` as `pivot_role_id`, `role_user`.`created_at` as `pivot_created_at`, `role_user`.`updated_at` as `pivot_updated_at` from `roles` inner join `role_user` on `roles`.`id` = `role_user`.`role_id` where `role_user`.`user_id` = ? and `roles`.`deleted_at` is null",
                "bindings": [
                    2
                ],
                "time": 73.97
            }
        ]
    }
  }
}
```

Testing API Responses
---------------------

[](#testing-api-responses)

Add `JsonAPI\Traits\Tests\JsonApiAsserts` trait to your default `TestCase` class and expand your tests with some useful asserts methods for testing API responses.

```
namespace Tests;

use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
use JsonAPI\Traits\Tests\JsonApiAsserts;

abstract class TestCase extends BaseTestCase
{
    use JsonApiAsserts;
}
```

Example of using additional asserts:

```
    /**
     * Testing GET /api/v1/entries/
     */
    public function test_read()
    {
        $response = $this->get("/api/v1/entries/1");

        // expecting to get response in JSON:API format and
        // find "id", "value", "type", "active" fields within
        // a response's data
        $this->assertJsonApiResponse($response, [
            "id",
            "value",
            "type",
            "active",
        ]);
    }
```

###  Health Score

48

—

FairBetter than 95% of packages

Maintenance49

Moderate activity, may be stable

Popularity31

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity85

Battle-tested with a long release history

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~41 days

Recently: every ~196 days

Total

43

Last Release

374d ago

Major Versions

v1.4.3 → v2.0.02020-12-28

v2.5 → v3.02022-02-09

v3.1.2 → v4.02023-03-17

PHP version history (6 changes)v1.1PHP ^7.4

v1.4.1PHP ^7.4|^8.0

v2.1.3PHP ^8.0

v3.0PHP ^8.1

v4.0.1PHP ^8.2

v4.2PHP ^8.4

### Community

Maintainers

![](https://www.gravatar.com/avatar/eb4811cd4e9b5cf313ec57367a04fe3b453acd77403cc59d7493c18726383d17?d=identicon)[serhiikamolov](/maintainers/serhiikamolov)

---

Top Contributors

[![serhiikamolov](https://avatars.githubusercontent.com/u/8070?v=4)](https://github.com/serhiikamolov "serhiikamolov (87 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/serhiikamolov-laravel-jsonapi/health.svg)

```
[![Health](https://phpackages.com/badges/serhiikamolov-laravel-jsonapi/health.svg)](https://phpackages.com/packages/serhiikamolov-laravel-jsonapi)
```

###  Alternatives

[laravel/cashier

Laravel Cashier provides an expressive, fluent interface to Stripe's subscription billing services.

2.5k25.9M107](/packages/laravel-cashier)[spatie/laravel-query-builder

Easily build Eloquent queries from API requests

4.4k26.9M220](/packages/spatie-laravel-query-builder)[laravel/pulse

Laravel Pulse is a real-time application performance monitoring tool and dashboard for your Laravel application.

1.7k12.1M99](/packages/laravel-pulse)[roots/acorn

Framework for Roots WordPress projects built with Laravel components.

9682.1M97](/packages/roots-acorn)[essa/api-tool-kit

set of tools to build an api with laravel

52680.5k](/packages/essa-api-tool-kit)[api-platform/laravel

API Platform support for Laravel

59126.4k6](/packages/api-platform-laravel)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
