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.