Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you force a JSON response on every response in Laravel?

I'm trying to build a REST api using Laravel Framework, I want a way to force the API to always responed with JSON not by doing this manulaly like:

return Response::json($data);

In other words I want every response to be JSON. Is there a good way to do that?

Update: The response must be JSON even on exceptions like not found exception.

like image 396
Mustafa Dwekat Avatar asked Apr 01 '16 22:04

Mustafa Dwekat


People also ask

Which method will automatically convert the array into appropriate JSON response in laravel?

The json method will automatically convert the array into appropriate json response.

How do I request a response in JSON?

To request JSON from a URL, you need to send an HTTP GET request to the server and provide the Accept: application/json request header with your request. The Accept header tells the server that our client is expecting JSON.

What is request expectsJson () in laravel?

Laravel Request: expectsJson() This function determines if current request expects a json response.

What is response JSON () return?

json() The json() method of the Response interface takes a Response stream and reads it to completion. It returns a promise which resolves with the result of parsing the body text as JSON .


2 Answers

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);
    }
like image 128
M165437 Avatar answered Oct 05 '22 17:10

M165437


Laravel Middleware is Extremely useful in this use case.

1. Make JsonResponseMiddleware middleware.

php artisan make:middleware JsonResponseMiddleware


namespace App\Http\Middleware;

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

class JsonResponseMiddleware
{
    /**
     * @var ResponseFactory
     */
    protected $responseFactory;

    /**
     * JsonResponseMiddleware constructor.
     */
    public function __construct(ResponseFactory $responseFactory)
    {
        $this->responseFactory = $responseFactory;
    }

    /**
     * Handle an incoming request.
     *
     * @param Request $request
     * @param Closure $next
     * @return mixed
     */
    public function handle(Request $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->responseFactory->json(
                $response->content(),
                $response->status(),
                $response->headers->all()
            );
        }

        return $response;
    }
}

2. Registor middleware in App\Http\Kernel.php

protected $middlewareGroups = [

        'api' => [
            ...
            ....
            /// Force to Json response (Our created Middleware)
            \App\Http\Middleware\JsonResponseMiddleware::class,
        ],


        'web' => [
            ...
            ....
            /// Add Here as well if we want to force response in web routes too.
        ],
]

Now we will receive every response in JSON only.

Please note that: Even exceptions will respond in JSON format

like image 25
dipenparmar12 Avatar answered Oct 05 '22 19:10

dipenparmar12