Skip to content

Commit a863c5f

Browse files
committed
Added json schema validation feature
1 parent f4293aa commit a863c5f

File tree

6 files changed

+121
-1
lines changed

6 files changed

+121
-1
lines changed

ArrayAccess/ArrayAccess.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
use BadMethodCallException;
77
use Mschindler83\ArrayAccess\DotAnnotation\DotAnnotation;
8+
use Opis\JsonSchema\Schema;
9+
use Opis\JsonSchema\Validator;
810

911
/**
1012
* @method string string(...$path)
@@ -31,6 +33,21 @@ public static function create($value): self
3133
return new self($value);
3234
}
3335

36+
public static function createWithJsonSchemaValidation($value, string $jsonSchemaDefinition): self
37+
{
38+
if (!is_array($value)) {
39+
throw ArrayAccessFailed::notAnArray($value);
40+
}
41+
$schema = Schema::fromJsonString($jsonSchemaDefinition);
42+
$result = (new Validator())->schemaValidation(\json_decode(\json_encode($value)), $schema, 10);
43+
44+
if (!$result->isValid()) {
45+
throw ArrayAccessFailed::jsonSchemaValidationFailed(...$result->getErrors());
46+
}
47+
48+
return new self($value);
49+
}
50+
3451
public static function newFromDotAnnotation(DotAnnotation ...$dotAnnotations): self
3552
{
3653
$newArray = [];

ArrayAccess/ArrayAccessFailed.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
namespace Mschindler83\ArrayAccess;
55

6+
use Opis\JsonSchema\ValidationError;
7+
68
class ArrayAccessFailed extends \RuntimeException
79
{
810
public static function notAnArray($value): self
@@ -51,4 +53,22 @@ public static function pathNotFound(): self
5153
{
5254
return new self('Path not found');
5355
}
56+
57+
public static function jsonSchemaValidationFailed(ValidationError ...$errors): self
58+
{
59+
$messages = \array_map(
60+
function (ValidationError $error) {
61+
return \sprintf(
62+
'Error: [%s], Data pointer: [%s]',
63+
$error->keyword(),
64+
\implode(', ', $error->dataPointer()),
65+
);
66+
},
67+
$errors
68+
);
69+
70+
return new self(
71+
\sprintf('Json schema validation failed: %s', \implode(', ', $messages))
72+
);
73+
}
5474
}

README.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Library to ease array access handling
88
## Features
99

1010
- Savely access typed values from a given array
11+
- Optional JSON schema validation
1112
- Support for datetime parsing
1213
- Define your own validation callback when retrieving values
1314
- Create a new array in form of "dot annotations"
@@ -69,6 +70,37 @@ Array
6970
)
7071
)
7172
```
73+
### Array access with JSON schema validation
74+
```
75+
$data = [
76+
'key1' => 'value1',
77+
'key2' => true,
78+
];
79+
80+
$access = ArrayAccess::createWithJsonSchemaValidation($data, \file_get_contents('json-schema.json'));
81+
82+
```
83+
84+
JSON schema: <json-schema.json>
85+
```
86+
{
87+
"$schema": "http://json-schema.org/draft-07/schema#",
88+
"type": "object",
89+
"properties": {
90+
"key1": {
91+
"type": "string",
92+
"minLength": 3,
93+
"maxLength": 64,
94+
"pattern": "^[a-zA-Z0-9\\-]+(\\s[a-zA-Z0-9\\-]+)*$"
95+
},
96+
"key2": {
97+
"type": "boolean"
98+
}
99+
},
100+
"required": ["key1", "key2"],
101+
"additionalProperties": false
102+
}
103+
```
72104

73105
### Access values
74106
```

Tests/ArrayAccess/ArrayAccessTest.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,38 @@ public function it_returns_array_data(): void
2828
static::assertSame($testArray, $access->data());
2929
}
3030

31+
/**
32+
* @test
33+
*/
34+
public function it_validates_with_json_schema_validator(): void
35+
{
36+
$data = [
37+
'key1' => 'value1',
38+
'key2' => true,
39+
];
40+
41+
$access = ArrayAccess::createWithJsonSchemaValidation($data, \file_get_contents(__DIR__ . '/../Fixture/json-schema.json'));
42+
static::assertSame('value1', $access->string('key1'));
43+
static::assertTrue($access->bool('key2'));
44+
}
45+
46+
/**
47+
* @test
48+
*/
49+
public function it_raises_an_exception_on_failed_json_schema_validation(): void
50+
{
51+
$this->expectException(ArrayAccessFailed::class);
52+
$this->expectExceptionMessage('Json schema validation failed: Error: [minLength], Data pointer: [key1], Error: [type], Data pointer: [key2], Error: [additionalProperties], Data pointer: []');
53+
54+
$data = [
55+
'key1' => 'v',
56+
'key2' => '1',
57+
'key3' => 'some-other-value',
58+
];
59+
60+
ArrayAccess::createWithJsonSchemaValidation($data, \file_get_contents(__DIR__ . '/../Fixture/json-schema.json'));
61+
}
62+
3163
/**
3264
* @test
3365
*/

Tests/Fixture/json-schema.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-07/schema#",
3+
"type": "object",
4+
"properties": {
5+
"key1": {
6+
"type": "string",
7+
"minLength": 3,
8+
"maxLength": 64,
9+
"pattern": "^[a-zA-Z0-9\\-]+(\\s[a-zA-Z0-9\\-]+)*$"
10+
},
11+
"key2": {
12+
"type": "boolean"
13+
}
14+
},
15+
"required": ["key1", "key2"],
16+
"additionalProperties": false
17+
}

composer.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
"license": "MIT",
66

77
"require": {
8-
"php": ">=7.4"
8+
"php": ">=7.4",
9+
"opis/json-schema": "^1.0",
10+
"ext-json": "*"
911
},
1012
"require-dev": {
1113
"phpunit/phpunit": "^8.5"

0 commit comments

Comments
 (0)