Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
3 / 3
CRAP
100.00% covered (success)
100.00%
1 / 1
JsonResponse
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
3 / 3
3
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
 getPayload
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 withPayload
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3declare(strict_types=1);
4
5/**
6 * This file is part of php-fast-forward/http-message.
7 *
8 * This source file is subject to the license bundled
9 * with this source code in the file LICENSE.
10 *
11 * @copyright Copyright (c) 2025-2026 Felipe SayĆ£o Lobato Abreu <github@mentordosnerds.com>
12 * @license   https://opensource.org/licenses/MIT MIT License
13 *
14 * @see       https://github.com/php-fast-forward/http-message
15 * @see       https://github.com/php-fast-forward
16 * @see       https://datatracker.ietf.org/doc/html/rfc2119
17 */
18
19namespace FastForward\Http\Message;
20
21use FastForward\Http\Message\Header\ContentType;
22use Nyholm\Psr7\Response;
23
24/**
25 * Class JsonResponse.
26 *
27 * Provides a JSON-specific HTTP response implementation that complies with PSR-7 Response interfaces.
28 * This class MUST be used when returning JSON payloads over HTTP responses.
29 * It automatically sets the 'Content-Type' header to 'application/json' with the specified charset.
30 *
31 * @method PayloadStreamInterface getBody() Retrieves the response body as a JSON stream.
32 */
33final class JsonResponse extends Response implements PayloadResponseInterface
34{
35    /**
36     * Constructs a new JsonResponse instance with an optional payload and charset.
37     *
38     * This constructor SHALL initialize the response body with a JsonStream containing the provided payload.
39     * The 'Content-Type' header MUST be set to 'application/json' with the specified charset.
40     *
41     * @param mixed $payload The JSON-serializable payload to send in the response body. Defaults to an empty array.
42     * @param string $charset The character encoding to use in the 'Content-Type' header. Defaults to 'utf-8'.
43     * @param array $headers
44     */
45    public function __construct(mixed $payload = [], string $charset = 'utf-8', array $headers = [])
46    {
47        $headers['Content-Type'] = ContentType::ApplicationJson->withCharset($charset);
48
49        parent::__construct(
50            headers: $headers,
51            body: new JsonStream($payload),
52        );
53    }
54
55    /**
56     * Retrieves the payload contained in the response body.
57     *
58     * This method MUST return the same payload provided during construction or via withPayload().
59     *
60     * @return mixed the decoded JSON payload
61     */
62    public function getPayload(): mixed
63    {
64        return $this->getBody()
65            ->getPayload();
66    }
67
68    /**
69     * Returns an instance with the specified payload.
70     *
71     * This method SHALL return a new instance of the response with the body replaced by a new JsonStream
72     * containing the provided payload. The original instance MUST remain unchanged, ensuring immutability
73     * as required by PSR-7.
74     *
75     * @param mixed $payload the new JSON-serializable payload
76     *
77     * @return self a new JsonResponse instance with the updated payload
78     */
79    public function withPayload(mixed $payload): self
80    {
81        return $this->withBody($this->getBody()->withPayload($payload));
82    }
83}