How do you force a JSON response on every response in Laravel?
Create a middleware as suggested by Alexander Lichter that sets the Accept
header on every request:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class ForceJsonResponse
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle(Request $request, Closure $next)
{
$request->headers->set('Accept', 'application/json');
return $next($request);
}
}
Add it to $routeMiddleware
in the app/Http/Kernel.php
file:
protected $routeMiddleware = [
(...)
'json.response' => \App\Http\Middleware\ForceJsonResponse::class,
];
You can now wrap all routes that should return JSON:
Route::group(['middleware' => ['json.response']], function () { ... });
Edit: For Laravel 6.9+
Give the json.response
middleware priority over other middlewares - to handle cases where the request is terminated by other middlewares (such as the Authorize
middleware) before you get to set the Accept
header.
To do this - override the constructor of you App\Http\Kernel
class (app/Http/Kernel.php
) with:
public function __construct( Application $app, Router $router ) {
parent::__construct( $app, $router );
$this->prependToMiddlewarePriority(\App\Http\Middleware\ForceJsonResponse::class);
}
I know this has been answered but these are not good solutions because they change the status code in unpredictable ways. the best solution is to either add the appropriate headers so that Laravel returns JSON (I think its Accept: application/json
), or follow this great tutorial to just always tell Laravel to return JSON: https://hackernoon.com/always-return-json-with-laravel-api-870c46c5efb2
You could probably also do this through middleware as well if you wanted to be more selective or accommodate a more complex solution.
To return JSON
in the controller just return $data;
For a JSON
response on errors, go to app\Exceptions\Handler.php
file and look at the render
method.
You should be able to re-write it to look something like this:
public function render($request, Exception $e)
{
// turn $e into an array.
// this is sending status code of 500
// get headers from $request.
return response()->json($e, 500);
}
However you will have to decide what to do with $e
, because it needs to be an array
. You can also set the status code and header array.
But then on any error, it will return a JSON
response.
Edit: It's also good to note that you can change the report
method to handle how laravel logs the error as well. More info here.