5
5
use Exception ;
6
6
use Illuminate \Contracts \Validation \Rule ;
7
7
use Illuminate \JsonSchema \JsonSchema as Schema ;
8
+ use JsonException ;
8
9
use Opis \JsonSchema \Errors \ValidationError ;
9
10
use Opis \JsonSchema \Validator ;
10
11
11
12
class JsonSchema implements Rule
12
13
{
13
- /**
14
- * The JSON schema instance.
15
- */
16
- protected Schema $ schema ;
17
-
18
14
/**
19
15
* The validation error message.
20
16
*/
@@ -23,9 +19,8 @@ class JsonSchema implements Rule
23
19
/**
24
20
* Create a new JSON schema validation rule.
25
21
*/
26
- public function __construct (Schema $ schema )
22
+ public function __construct (protected Schema $ schema )
27
23
{
28
- $ this ->schema = $ schema ;
29
24
}
30
25
31
26
/**
@@ -41,27 +36,31 @@ public function passes($attribute, $value): bool
41
36
// Normalize the data to what Opis expects
42
37
$ data = $ this ->normalizeData ($ value );
43
38
44
- if ($ data === null && $ this ->errorMessage ) {
39
+ if ($ data === null && $ this ->errorMessage !== null ) {
45
40
return false ;
46
41
}
47
42
48
43
try {
49
- $ validator = new Validator ;
50
- $ schemaString = $ this ->schema ->toString ();
51
- $ result = $ validator ->validate ($ data , $ schemaString );
44
+ $ result = (new Validator )->validate ($ data , $ this ->schema ->toString ());
52
45
53
- if (! $ result ->isValid ()) {
54
- $ this ->errorMessage = $ this ->formatValidationError ($ result ->error ());
55
-
56
- return false ;
46
+ if ($ result ->isValid ()) {
47
+ return true ;
57
48
}
58
49
59
- return true ;
50
+ $ this -> errorMessage = $ this -> formatValidationError ( $ result -> error ()) ;
60
51
} catch (Exception $ e ) {
61
52
$ this ->errorMessage = "Schema validation error: {$ e ->getMessage ()}" ;
62
-
63
- return false ;
64
53
}
54
+
55
+ return false ;
56
+ }
57
+
58
+ /**
59
+ * Get the validation error message.
60
+ */
61
+ public function message (): string
62
+ {
63
+ return $ this ->errorMessage ?? 'The :attribute does not match the required schema. ' ;
65
64
}
66
65
67
66
/**
@@ -72,46 +71,34 @@ public function passes($attribute, $value): bool
72
71
*/
73
72
protected function normalizeData ($ value )
74
73
{
75
- if (is_string ($ value )) {
76
- $ decoded = json_decode ($ value );
77
-
78
- if (json_last_error () !== JSON_ERROR_NONE ) {
79
- $ this ->errorMessage = 'Invalid JSON format: ' .json_last_error_msg ();
80
-
81
- return null ;
82
- }
83
-
84
- return $ decoded ;
85
- }
86
-
87
74
if (is_array ($ value ) || is_object ($ value )) {
88
75
// Convert to JSON and back to ensure proper object/array structure for Opis
89
76
return json_decode (json_encode ($ value , JSON_FORCE_OBJECT ), false );
90
77
}
91
78
92
- return $ value ;
79
+ if (! is_string ($ value )) {
80
+ return $ value ;
81
+ }
82
+
83
+ try {
84
+ return json_decode ($ value , false , 512 , JSON_THROW_ON_ERROR );
85
+ } catch (JsonException $ e ) {
86
+ $ this ->errorMessage = "Invalid JSON format: {$ e ->getMessage ()}" ;
87
+
88
+ return null ;
89
+ }
93
90
}
94
91
95
92
/**
96
93
* Format the validation error message.
97
94
*/
98
- protected function formatValidationError (? ValidationError $ error ): string
95
+ protected function formatValidationError (ValidationError $ error ): string
99
96
{
100
97
$ keyword = $ error ->keyword ();
101
98
$ dataPath = implode ('. ' , $ error ->data ()->path () ?? []);
102
99
103
- if ($ dataPath ) {
104
- return "Validation failed at ' {$ dataPath }': {$ keyword }" ;
105
- }
106
-
107
- return "Validation failed: {$ keyword }" ;
108
- }
109
-
110
- /**
111
- * Get the validation error message.
112
- */
113
- public function message (): string
114
- {
115
- return $ this ->errorMessage ?? 'The :attribute does not match the required schema. ' ;
100
+ return $ dataPath !== '' ?
101
+ "Validation failed at ' $ dataPath': $ keyword " :
102
+ "Validation failed: $ keyword " ;
116
103
}
117
104
}
0 commit comments