Laravel Lumen Asegurar respuesta JSON

3 minutos de lectura

Avatar de usuario de John Fonseka
Juan Fonseka

Soy nuevo en Laravel y en Lumen. Quiero asegurarme de que siempre obtengo solo un objeto JSON como salida. ¿Cómo puedo hacer esto en Lumen?

Puedo obtener una respuesta JSON usando response()->json($response);. Pero cuando ocurre un error, la API me da text/html errores pero solo quiero application/json respuestas

Gracias por adelantado.

Avatar de usuario de Wader
Ave zancuda

Deberá ajustar su controlador de excepciones (app/Exceptions/Handler.php) para devolver la respuesta que desea.

Este es un ejemplo muy básico de lo que se puede hacer.

public function render($request, Exception $e)
{
    $rendered = parent::render($request, $e);

    return response()->json([
        'error' => [
            'code' => $rendered->getStatusCode(),
            'message' => $e->getMessage(),
        ]
    ], $rendered->getStatusCode());
}

  • Gracias por la respuesta. Sin embargo, tengo una pequeña pregunta, ¿puedo hacer esto? return response()->json(['code' => $rendered->getStatusCode(), 'message' => $e->getMessage()], $rendered->getStatusCode()); Busqué la lista de excepciones y no pude encontrar una lista todavía.

    – Juan Fonseka

    18 mayo 2016 a las 10:50


  • Eso me parece bien. Aquí está la firma del response()->json() función. github.com/laravel/lumen-framework/blob/5.2/src/Http/…

    – Vadeador

    18 mayo 2016 a las 11:02

  • Tenga en cuenta que este ejemplo siempre devolverá un 200 Código HTTP. Probablemente no quieras eso. si usa findOrFail() por ejemplo, el code elemento mostrará correctamente un 404pero el resultado general seguirá siendo un 200, que evidentemente no lo es. Para arreglar esto, pasa $rendered->getStatusCode() dentro json() como su segundo parámetro.

    – Jasón

    29 de abril de 2019 a las 10:52

Una solución más precisa basada en la respuesta de @Wader puede ser:

use Illuminate\Http\JsonResponse;

public function render($request, Exception $e)
{
    $parentRender = parent::render($request, $e);

    // if parent returns a JsonResponse 
    // for example in case of a ValidationException 
    if ($parentRender instanceof JsonResponse)
    {
        return $parentRender;
    }

    return new JsonResponse([
        'message' => $e instanceof HttpException
            ? $e->getMessage()
            : 'Server Error',
    ], $parentRender->status());
}

  • Buena respuesta completa que incluye la clase necesaria también. voto positivo de mi parte

    – Derek Pollard

    29 de marzo de 2018 a las 6:01

  • ¿Alguna sugerencia para Lumen 8? Gracias

    – Kamlesh

    29 de julio de 2021 a las 12:47

Avatar de usuario de César Escudero
César Escudero

En lugar de tocar el controlador de excepciones, le sugiero que agregue un middleware que establezca el Accept encabezado a application/json.

Por ejemplo, puede crear un middleware llamado RequestsAcceptJson y definirlo de esta manera:

<?php

namespace App\Http\Middleware;

use Closure;

class RequestsAcceptJson
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        $acceptHeader = strtolower($request->headers->get('accept'));

        // If the accept header is not set to application/json
        // We attach it and continue the request
        if ($acceptHeader !== 'application/json') {
            $request->headers->set('Accept', 'application/json');
        }

        return $next($request);
    }
}

Luego, solo necesita registrarlo como un middleware global para que se ejecute en cada solicitud a su API. En lumen, puede hacerlo agregando la clase en la llamada de middleware dentro de su bootstrap/app.php

$app->middleware([
    App\Http\Middleware\RequestsAcceptJson::class
]);

Con Laravel es más o menos el mismo proceso. Ahora el controlador de errores siempre devolverá un json en lugar de texto sin formato/html.

Sé que esta es una pregunta bastante antigua, pero acabo de encontrarla. Por defecto, Lumen devolverá una respuesta JSON si el solicitante la “quiere”.

vendor/laravel/lumen-framework/src/Exceptions/Handler.php:110

return $request->expectsJson()
    ? $this->prepareJsonResponse($request, $e)
    : $this->prepareResponse($request, $e);

esto se reduce a
vendor/illuminate/http/Concerns/InteractsWithContentTypes.php:52

$acceptable = $this->getAcceptableContentTypes();
return isset($acceptable[0]) && Str::contains($acceptable[0], ['/json', '+json']);

Lo que significa que si especifica un encabezado “Aceptar” con lumen “aplicación/json”, automáticamente devolverá una respuesta JSON. p.ej curl -H "Accept: application/json" https://example.com/my-erroring-endpint

Usar esto le evita tener que escribir un controlador de errores personalizado.

¿Ha sido útil esta solución?