Skip to content

Commit 3bdaecd

Browse files
committed
Add JsonValidationError exception and improve JSON schema error message
1 parent 493397f commit 3bdaecd

File tree

5 files changed

+113
-27
lines changed

5 files changed

+113
-27
lines changed

src/Exception/JsonValidationError.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace EventEngine\JsonSchema\Exception;
6+
7+
8+
class JsonValidationError extends InvalidArgumentException
9+
{
10+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace EventEngine\JsonSchema\Exception;
6+
7+
8+
class JustinRainbowJsonValidationError extends JsonValidationError
9+
{
10+
/**
11+
* @var array
12+
*/
13+
private $errors;
14+
15+
public static function withError(string $objectName, ...$errors): JustinRainbowJsonValidationError
16+
{
17+
$self = new self('Validation of "' . $objectName . '" failed: ');
18+
$self->errors = $errors;
19+
20+
$self->message .= \array_reduce(
21+
$errors,
22+
static function ($message, array $error) use ($self) {
23+
return $message . "\n" . $self->errorMessage($error);
24+
}
25+
);
26+
27+
return $self;
28+
}
29+
30+
public function errors(): array
31+
{
32+
return $this->errors;
33+
}
34+
35+
public function errorMessage(array $error): string
36+
{
37+
return sprintf("[%s] %s\n", $error['property'], $error['message']);
38+
}
39+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace EventEngine\JsonSchema\Exception;
6+
7+
8+
use Opis\JsonSchema\ValidationError;
9+
10+
class OpisJsonValidationError extends JsonValidationError
11+
{
12+
/**
13+
* @var ValidationError[]
14+
*/
15+
private $errors;
16+
17+
public static function withError(string $objectName, ValidationError ...$validationErrors): OpisJsonValidationError
18+
{
19+
$self = new self('Validation of "' . $objectName . '" failed: ');
20+
$self->errors = $validationErrors;
21+
22+
foreach ($validationErrors as $error) {
23+
$self->message .= $self->errorMessage($error);
24+
25+
if ($error->subErrorsCount()) {
26+
$self->message .= \array_reduce(
27+
$error->subErrors(),
28+
static function ($message, ValidationError $error) use ($self) {
29+
return $message . "\n" . $self->errorMessage($error);
30+
}
31+
);
32+
}
33+
}
34+
35+
return $self;
36+
}
37+
38+
/**
39+
* @return ValidationError[]
40+
*/
41+
public function errors(): array
42+
{
43+
return $this->errors;
44+
}
45+
46+
public function errorMessage(ValidationError $error): string
47+
{
48+
$dataPointer = $error->dataPointer();
49+
50+
if (count($dataPointer) === 0) {
51+
return \sprintf('[%s] %s', $error->keyword(), \json_encode($error->keywordArgs(), JSON_PRETTY_PRINT));
52+
}
53+
54+
return \sprintf('field "%s" [%s] %s',
55+
implode('.', $dataPointer),
56+
$error->keyword(),
57+
\json_encode($error->keywordArgs(), JSON_PRETTY_PRINT)
58+
);
59+
}
60+
}

src/JustinRainbowJsonSchema.php

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
namespace EventEngine\JsonSchema;
1313

14-
use EventEngine\JsonSchema\Exception\InvalidArgumentException;
14+
use EventEngine\JsonSchema\Exception\JustinRainbowJsonValidationError;
1515
use JsonSchema\Validator;
1616

1717
final class JustinRainbowJsonSchema extends AbstractJsonSchema
@@ -30,17 +30,8 @@ public function assert(string $objectName, array $data, array $jsonSchema)
3030
$this->jsonValidator()->validate($enforcedObjectData, $jsonSchema);
3131

3232
if (! $this->jsonValidator()->isValid()) {
33-
$errors = $this->jsonValidator()->getErrors();
34-
3533
$this->jsonValidator()->reset();
36-
37-
foreach ($errors as $i => $error) {
38-
$errors[$i] = \sprintf("[%s] %s\n", $error['property'], $error['message']);
39-
}
40-
41-
throw new InvalidArgumentException(
42-
"Validation of $objectName failed: " . \implode("\n", $errors)
43-
);
34+
throw JustinRainbowJsonValidationError::withError($objectName, $this->jsonValidator()->getErrors());
4435
}
4536

4637
$this->jsonValidator()->reset();

src/OpisJsonSchema.php

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
namespace EventEngine\JsonSchema;
1313

14-
use EventEngine\JsonSchema\Exception\InvalidArgumentException;
14+
use EventEngine\JsonSchema\Exception\OpisJsonValidationError;
1515
use Opis\JsonSchema\Schema as OpisSchema;
1616
use Opis\JsonSchema\Validator;
1717

@@ -38,21 +38,7 @@ public function assert(string $objectName, array $data, array $jsonSchema)
3838
$result = $this->jsonValidator()->schemaValidation($enforcedObjectData, OpisSchema::fromJsonString(\json_encode($jsonSchema)));
3939

4040
if (! $result->isValid()) {
41-
$errors = [];
42-
43-
foreach ($result->getErrors() as $error) {
44-
$errors[] = \sprintf('[%s] %s', $error->keyword(), \json_encode($error->keywordArgs(), JSON_PRETTY_PRINT));
45-
46-
if ($error->subErrorsCount()) {
47-
foreach ($error->subErrors() as $subError) {
48-
$errors[] = \sprintf("[%s] %s\n", $subError->keyword(), \json_encode($subError->keywordArgs(), JSON_PRETTY_PRINT));
49-
}
50-
}
51-
}
52-
53-
throw new InvalidArgumentException(
54-
"Validation of $objectName failed: " . \implode("\n", $errors)
55-
);
41+
throw OpisJsonValidationError::withError($objectName, ...$result->getErrors());
5642
}
5743
}
5844

0 commit comments

Comments
 (0)