1818 */
1919final class JsonStream extends Stream implements JsonStreamInterface
2020{
21- /**
22- * @var resource The underlying stream resource containing the JSON-encoded data.
23- * This resource MUST be a writable PHP stream.
24- */
25- private $ stream ;
26-
27- /**
28- * @var mixed The original payload data prior to JSON encoding.
29- * This MAY be any JSON-encodable PHP type, excluding resources.
30- */
31- private mixed $ payload ;
21+ public const ENCODING_OPTIONS = JSON_THROW_ON_ERROR | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE ;
3222
3323 /**
3424 * Constructs a new JsonStream instance with the provided payload.
@@ -39,11 +29,14 @@ final class JsonStream extends Stream implements JsonStreamInterface
3929 * @param mixed $payload The data to encode as JSON. MUST be JSON-encodable. Resources are explicitly prohibited.
4030 * @param int $encodingOptions Optional JSON encoding flags as defined by {@see json_encode()}. Defaults to 0.
4131 */
42- public function __construct (mixed $ payload , private int $ encodingOptions = 0 )
43- {
44- $ this ->setPayload ($ payload );
32+ public function __construct (
33+ private mixed $ payload ,
34+ private int $ encodingOptions = self ::ENCODING_OPTIONS
35+ ) {
36+ parent ::__construct (fopen ('php://temp ' , 'wb+ ' ));
4537
46- parent ::__construct ($ this ->stream );
38+ $ this ->write ($ this ->jsonEncode ($ this ->payload , $ this ->encodingOptions ));
39+ $ this ->rewind ();
4740 }
4841
4942 /**
@@ -71,55 +64,13 @@ private function jsonEncode(mixed $data, int $encodingOptions): string
7164 return json_encode ($ data , $ encodingOptions | JSON_THROW_ON_ERROR );
7265 }
7366
74- /**
75- * Sets the payload and updates the underlying stream with its JSON-encoded form.
76- *
77- * This method SHALL encode the payload as JSON, write it to a temporary stream, and rewind the stream pointer.
78- * It also retains the original decoded payload for later access.
79- *
80- * @param mixed $data The data to encode as JSON. MUST be JSON-encodable.
81- * @return self The current instance for fluent chaining.
82- *
83- * @throws \InvalidArgumentException If the data contains a resource.
84- * @throws \JsonException If JSON encoding fails.
85- */
86- private function setPayload (mixed $ data ): self
87- {
88- $ contents = $ this ->jsonEncode ($ data , $ this ->encodingOptions );
89-
90- $ this ->payload = $ data ;
91- $ this ->stream = fopen ('php://temp ' , 'wb+ ' );
92-
93- $ this ->write ($ contents );
94- $ this ->rewind ();
95-
96- return $ this ;
97- }
98-
99- /**
100- * Retrieves the decoded payload previously provided to the stream.
101- *
102- * @return mixed The original decoded payload, which MAY be of any JSON-encodable PHP type.
103- */
10467 public function getPayload (): mixed
10568 {
10669 return $ this ->payload ;
10770 }
10871
109- /**
110- * Returns a new instance with the updated payload encoded as JSON.
111- *
112- * This method SHALL NOT modify the current instance. It MUST return a cloned instance with the new payload
113- * written to its stream.
114- *
115- * @param mixed $data The new data to encode as JSON. MUST be JSON-encodable.
116- * @return self A new instance with the updated JSON payload.
117- *
118- * @throws \InvalidArgumentException If the data contains a resource.
119- * @throws \JsonException If JSON encoding fails.
120- */
121- public function withPayload (mixed $ data ): self
72+ public function withPayload (mixed $ payload ): self
12273 {
123- return ( clone $ this )-> setPayload ( $ data );
74+ return new self ( $ payload );
12475 }
12576}
0 commit comments