Reputation: 123
I'm practicing to make a good RESTful API services following this guide from Google (https://google.github.io/styleguide/jsoncstyleguide.xml) for the json format response.
Is there any way to set the default JSON format for every response because in the guide said
In order to maintain a consistent interface across APIs, JSON objects should follow the structure outlined below.
object {
string apiVersion?;
string context?;
string id?;
string method?;
object {
string id?
}* params?;
object {
string kind?;
string fields?;
string etag?;
string id?;
string lang?;
string updated?; # date formatted RFC 3339
boolean deleted?;
integer currentItemCount?;
integer itemsPerPage?;
integer startIndex?;
integer totalItems?;
integer pageIndex?;
integer totalPages?;
string pageLinkTemplate /^https?:/ ?;
object {}* next?;
string nextLink?;
object {}* previous?;
string previousLink?;
object {}* self?;
string selfLink?;
object {}* edit?;
string editLink?;
array [
object {}*;
] items?;
}* data?;
object {
integer code?;
string message?;
array [
object {
string domain?;
string reason?;
string message?;
string location?;
string locationType?;
string extendedHelp?;
string sendReport?;
}*;
] errors?;
}* error?;
}*;
I'm practicing with Laravel 5.4. Should I just make a trait and use make own JSON response format? Because, it's so cumbersome having to write that kind of response every time you return a JSON response.
Upvotes: 1
Views: 6695
Reputation: 29
In Laravel 11, you can use middleware
to intercept the response object.
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class ResponseAPI
{
/**
* Handle an incoming request.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next): Response
{
$response = $next($request);
if (in_array($response->status(), [200, 201, 404, 401, 422])) {
$response->header('Content-Type', 'application/json');
}
return $response;
}
}
Since Kernel.php
is no longer available in Laravel 11, you can add the middleware in bootstrap/app.php
.
<?php
use App\Http\Middleware\ResponseAPI;
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;
return Application::configure(basePath: dirname(__DIR__))
->withRouting(
// web: __DIR__.'/../routes/web.php',
api: __DIR__.'/../routes/api.php',
commands: __DIR__.'/../routes/console.php',
health: '/up',
)
->withMiddleware(function (Middleware $middleware) {
$middleware->append(ResponseAPI::class); // Your costum middleware
})
->withExceptions(function (Exceptions $exceptions) {
//
})
->create();
Since the middleware is applied globally, all your response should be returned in json format.
Upvotes: 0
Reputation: 480
You can add middleware to force a JSON response by setting the "accepts" header on the incoming request. Include that middleware in HttpKernel
's $middlewareGroups['api']
to cover all api routes. This is a Laravel ^7.0 solution.
<?php
# app/Http/Middleware/JsonResponse.php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class JsonResponse {
/**
* Set 'Accept' header to force a JSON response for API routes.
*
* @param Request $request
* @param Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
$request->header->set('accept', 'application/json');
return $response;
}
}
--
<?php
# app/Http/Kernel.php
.
.
.
protected $middlewareGroups = [
'web' => [...],
'api' => [
'throttle:60,1',
ApiJsonResponse::class
]
];
Credit to Alfredo EM for leading me to this solution.
Upvotes: 0
Reputation: 2069
You can use a Middleware
to intercept the response object and format it as you like, for example I usually use this to append headers in the response:
<?php
# app/Http/Middleware/ResponseAPI.php
namespace App\Http\Middleware;
use Closure;
class ResponseAPI {
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param string|null $guard
* @return mixed
*/
public function handle($request, Closure $next, $guard = null)
{
$response = $next($request);
if (in_array($response->status(), [200, 201, 404, 401, 422])) {
$response->header('Content-Type', 'application/json');
}
return $response;
}
}
--
<?php
# app/Http/Kernel.php
.
.
.
protected $routeMiddleware = [
# others middlewares
'api.response' => \App\Http\Middleware\ResponseAPI::class
];
--
<?php
# app/Http/routes.php
$app->group(['prefix' => 'api/v1', 'middleware' => ['api.response']], function($app) {
# all routes
});
Upvotes: 5
Reputation: 566
You can use toJson()
method.
https://laravel.com/docs/5.4/collections#method-tojson https://laravel.com/docs/5.4/pagination#converting-results-to-json
Upvotes: 0