Skip to content

Commit 12da373

Browse files
committed
Update Json.php
1 parent 809601d commit 12da373

1 file changed

Lines changed: 121 additions & 3 deletions

File tree

‎src/Filesystem/Json.php‎

Lines changed: 121 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,21 @@ final class Json extends File
2727
* @param string $file
2828
* @param bool $isArray
2929
* @return mixed
30+
* @throws \InvalidArgumentException When file is invalid
31+
* @throws \RuntimeException When JSON parsing fails
3032
*/
3133
public static function parse(string $file, bool $isArray = false) : mixed
3234
{
33-
return self::decode(self::r($file), $isArray);
35+
if ( empty($file) ) {
36+
throw new \InvalidArgumentException('File path must be a non-empty string');
37+
}
38+
39+
$content = self::r($file);
40+
if ( $content === false || $content === null ) {
41+
throw new \RuntimeException("Unable to read file: {$file}");
42+
}
43+
44+
return self::decode($content, $isArray);
3445
}
3546

3647
/**
@@ -40,10 +51,28 @@ public static function parse(string $file, bool $isArray = false) : mixed
4051
* @param string $value
4152
* @param bool $isArray
4253
* @return mixed
54+
* @throws \InvalidArgumentException When input is invalid
55+
* @throws \RuntimeException When JSON decoding fails
4356
*/
4457
public static function decode(string $value, bool $isArray = false) : mixed
4558
{
46-
return json_decode($value, $isArray);
59+
// Input validation
60+
if ( empty($value) ) {
61+
throw new \InvalidArgumentException('JSON string cannot be empty');
62+
}
63+
64+
// Security
65+
$maxDepth = 512;
66+
$result = json_decode($value, $isArray, $maxDepth);
67+
68+
// Check for errors
69+
$error = self::lastError();
70+
if ( $error !== JSON_ERROR_NONE ) {
71+
$errorMessage = self::getError($error);
72+
throw new \RuntimeException("JSON decode error: {$errorMessage}");
73+
}
74+
75+
return $result;
4776
}
4877

4978
/**
@@ -52,6 +81,8 @@ public static function decode(string $value, bool $isArray = false) : mixed
5281
* @access public
5382
* @param mixed $value
5483
* @return mixed
84+
* @throws \InvalidArgumentException When value cannot be encoded
85+
* @throws \RuntimeException When JSON encoding fails
5586
*/
5687
public static function encode($value) : mixed
5788
{
@@ -70,9 +101,96 @@ public static function encode($value) : mixed
70101
* @param int $flags
71102
* @param int $depth
72103
* @return mixed
104+
* @throws \InvalidArgumentException When parameters are invalid
105+
* @throws \RuntimeException When JSON encoding fails
73106
*/
74107
public static function format($value, int $flags = 64 | 256, int $depth = 512) : mixed
75108
{
76-
return json_encode($value, $flags, $depth);
109+
// Validate depth parameter
110+
if ( $depth < 1 || $depth > 2147483647 ) {
111+
throw new \InvalidArgumentException('Depth must be between 1 and 2147483647');
112+
}
113+
114+
// Validate value is encodable
115+
if ( is_resource($value) ) {
116+
throw new \InvalidArgumentException('Cannot encode resource type');
117+
}
118+
119+
// Encode with error handling
120+
$result = json_encode($value, $flags, $depth);
121+
122+
// Check for errors
123+
$error = self::lastError();
124+
if ( $error !== JSON_ERROR_NONE ) {
125+
$errorMessage = self::getError($error);
126+
throw new \RuntimeException("JSON encode error: {$errorMessage}");
127+
}
128+
129+
return $result;
130+
}
131+
132+
/**
133+
* Validate JSON string.
134+
*
135+
* @access public
136+
* @param string $value
137+
* @return bool
138+
*/
139+
public static function isValid(string $value) : bool
140+
{
141+
if ( empty($value) ) {
142+
return false;
143+
}
144+
145+
json_decode($value);
146+
return self::lastError() === JSON_ERROR_NONE;
147+
}
148+
149+
/**
150+
* Get JSON last error.
151+
*
152+
* @access public
153+
* @return int
154+
*/
155+
public static function lastError() : int
156+
{
157+
return json_last_error();
158+
}
159+
160+
/**
161+
* Get human-readable JSON error message.
162+
*
163+
* @access private
164+
* @param int $error
165+
* @return string
166+
*/
167+
private static function getError(int $error) : string
168+
{
169+
switch ($error) {
170+
case JSON_ERROR_NONE:
171+
return 'No error';
172+
case JSON_ERROR_DEPTH:
173+
return 'Maximum stack depth exceeded';
174+
case JSON_ERROR_STATE_MISMATCH:
175+
return 'State mismatch (invalid or malformed JSON)';
176+
case JSON_ERROR_CTRL_CHAR:
177+
return 'Control character error';
178+
case JSON_ERROR_SYNTAX:
179+
return 'Syntax error, malformed JSON';
180+
case JSON_ERROR_UTF8:
181+
return 'Malformed UTF-8 characters';
182+
case JSON_ERROR_RECURSION:
183+
return 'One or more recursive references in the value to be encoded';
184+
case JSON_ERROR_INF_OR_NAN:
185+
return 'One or more NAN or INF values in the value to be encoded';
186+
case JSON_ERROR_UNSUPPORTED_TYPE:
187+
return 'A value of a type that cannot be encoded was given';
188+
case JSON_ERROR_INVALID_PROPERTY_NAME:
189+
return 'A property name that cannot be encoded was given';
190+
case JSON_ERROR_UTF16:
191+
return 'Malformed UTF-16 characters';
192+
default:
193+
return "Unknown JSON error (code: {$error})";
194+
}
77195
}
78196
}

0 commit comments

Comments
 (0)