Laravel: Convert all responses to JSON automatically

Because not every person in the world wants HTML, nor use response()->json() in every freaking controller.

And it will be

The Middleware

Well, there is very simple way to “force” your app to return JSON, and that is with one line middleware. We will call it JsonMiddleware because indicates the response should be JSON, but doesn’t forces it.

<?php

namespace App\Http\Middleware;

use Closure;

class JsonMiddleware
{
/**
* Handle an incoming request.
*
*
@param \Illuminate\Http\Request $request
*
@param \Closure $next
*
@return mixed
*/
public function handle($request, Closure $next)
{
$request->headers->set('Accept', 'application/json');

return $next($request);
}
}

The place

In our App\Http\Kernel.php, we can find the list of middlewares the App manages.

/**
* The application's route middleware groups.
*
*
@var array
*/
protected $middlewareGroups = [
'web' => [
// ...
],

'api' => [
'throttle:60,1',
'bindings',

// Our new JSON Middleware
\App\Http\Middleware\Api\JsonMiddleware::class,
],
];
/**
* The application's route middleware.
*
* These middleware may be assigned to groups or used individually.
*
*
@var array
*/
protected $routeMiddleware = [
// ...

// Register the alias for the JSON middleware
'return-json' => \App\Http\Middleware\Api\JsonMiddleware::class,
];
Route::namespace('User')
->middleware(['api', 'return-json']) // Use our JSON Middleware
->group(function () {
Route::get('user/profile', 'UserController@profile');
Route::get('user/calls', 'UserController@calls');
);

The Order

Laravel conveniently has a global order for middlewares. When they are called in a route, it will run them in the same order displayed on $middlewarePriority.

/**
* The priority-sorted list of middleware.
*
* This forces the listed middleware to always be in the given order.
*
*
@var array
*/
protected $middlewarePriority = [
// Put the JSON Middleware first
\App\Http\Middleware\Api\JsonMiddleware::class,
// Then the rest...
];

Bonus: Forcing a JSON Response

Additionally to our JsonMiddleware, we can ensure the response is a Illuminate\Http\JsonResponse instance.

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Contracts\Routing\ResponseFactory;
use Illuminate\Http\JsonResponse;

class JsonMiddleware
{
/**
* The Response Factory our app uses
*
*
@var ResponseFactory
*/
protected $factory;

/**
* JsonMiddleware constructor.
*
*
@param ResponseFactory $factory
*/
public function __construct(ResponseFactory $factory)
{
$this->factory = $factory;
}

/**
* Handle an incoming request.
*
*
@param \Illuminate\Http\Request $request
*
@param \Closure $next
*
@return mixed
*/
public function handle($request, Closure $next)
{
// First, set the header so any other middleware knows we're
// dealing with a should-be JSON response.
$request->headers->set('Accept', 'application/json');

// Get the response
$response = $next($request);

// If the response is not strictly a JsonResponse, we make it
if (!$response instanceof JsonResponse) {
$response = $this->factory->json(
$response->content(),
$response->status(),
$response->headers->all()
);
}

return $response;

}
}

Graphic Designer graduate. Full Stack Web Developer. Retired Tech & Gaming Editor.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store