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