Skip to content

Commit 6e4e4f7

Browse files
author
Alexander Miertsch
authored
Merge pull request #13 from event-engine/feature/support-json-pointer-in-type-name
feat: Support JsonPointer in type name
2 parents eaa0083 + 98a7582 commit 6e4e4f7

File tree

2 files changed

+134
-2
lines changed

2 files changed

+134
-2
lines changed

src/AbstractJsonSchema.php

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
use EventEngine\Schema\Schema;
2626
use EventEngine\Schema\TypeSchemaMap;
2727
use EventEngine\Util\VariableType;
28+
use function array_key_exists;
29+
use function explode;
2830

2931
abstract class AbstractJsonSchema implements Schema
3032
{
@@ -34,7 +36,7 @@ public function assertPayload(string $messageName, array $payload, PayloadSchema
3436
{
3537
$this->assertPayloadSchema($messageName, $payloadSchema);
3638

37-
$payloadSchemaArr = array_merge($payloadSchema->toArray(), [JsonSchema::DEFINITIONS => $typeSchemaMap->toArray()]);
39+
$payloadSchemaArr = array_merge($payloadSchema->toArray(), [JsonSchema::DEFINITIONS => $this->convertTypeSchemaMapToDefinitions($typeSchemaMap)]);
3840

3941
$this->assert("$messageName payload", $payload, $payloadSchemaArr);
4042
}
@@ -123,7 +125,26 @@ public function buildMessageBoxSchema(CommandMap $commandMap, EventMap $eventMap
123125
'events' => $eventSchemas,
124126
'queries' => $querySchemas,
125127
],
126-
'definitions' => $typeSchemaMap->toArray(),
128+
'definitions' => $this->convertTypeSchemaMapToDefinitions($typeSchemaMap),
127129
];
128130
}
131+
132+
private function convertTypeSchemaMapToDefinitions(TypeSchemaMap $typeSchemaMap): array
133+
{
134+
$definitions = [];
135+
136+
foreach ($typeSchemaMap->toArray() as $jsonPointer => $typeSchema) {
137+
$temp = &$definitions;
138+
foreach(explode("/", $jsonPointer) as $key) {
139+
if(!array_key_exists($key, $temp)) {
140+
$temp[$key] = [];
141+
}
142+
$temp = &$temp[$key];
143+
}
144+
$temp = $typeSchema;
145+
unset($temp);
146+
}
147+
148+
return $definitions;
149+
}
129150
}

tests/TypeSchemaReferenceTest.php

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace EventEngineTest\JsonSchema;
5+
6+
use EventEngine\JsonSchema\Exception\JsonValidationError;
7+
use EventEngine\JsonSchema\JsonSchema;
8+
use EventEngine\JsonSchema\JsonSchemaArray;
9+
use EventEngine\JsonSchema\OpisJsonSchema;
10+
use EventEngine\Schema\TypeSchemaMap;
11+
use function json_decode;
12+
13+
final class TypeSchemaReferenceTest extends BasicTestCase
14+
{
15+
private function schema(): array
16+
{
17+
$schema = <<<'JSON'
18+
{
19+
"$schema": "http://json-schema.org/draft-07/schema#",
20+
"type": "object",
21+
"properties": {
22+
"name": {
23+
"$ref": "#/definitions/Name"
24+
},
25+
"hasValue": {"type": "boolean"},
26+
"age": {"type": "number"},
27+
"subObject": {
28+
"type": "object",
29+
"properties": {
30+
"p1": {
31+
"$ref": "#/definitions/SubObject/P1"
32+
},
33+
"p2": {
34+
"$ref": "#/definitions/SubObject/P2"
35+
}
36+
},
37+
"required": ["p1", "p2"],
38+
"additionalProperties": false
39+
},
40+
"type": {
41+
"enum": ["Foo", "Bar", "Baz"]
42+
}
43+
},
44+
"required": ["name", "hasValue", "age", "type", "subObject"],
45+
"additionalProperties": false
46+
}
47+
JSON;
48+
return json_decode($schema, true);
49+
}
50+
51+
private function typeSchemaMap(): TypeSchemaMap
52+
{
53+
$typeSchemaMap = new TypeSchemaMap();
54+
55+
$typeSchemaMap->add('Name', JsonSchema::string(['minLength' => 3]));
56+
$typeSchemaMap->add('SubObject/P1', JsonSchema::string(['minLength' => 3]));
57+
$typeSchemaMap->add('SubObject/P2', JsonSchema::boolean());
58+
59+
return $typeSchemaMap;
60+
}
61+
62+
private function validData(): array
63+
{
64+
return [
65+
'name' => 'Tester',
66+
'hasValue' => true,
67+
'age' => 40,
68+
'type' => 'Bar',
69+
'subObject' => [
70+
'p1' => 'a sub str',
71+
'p2' => true
72+
]
73+
];
74+
}
75+
76+
/**
77+
* @test
78+
*/
79+
public function it_validates_payload_schema(): void
80+
{
81+
$data = $this->validData();
82+
83+
$cut = new OpisJsonSchema();
84+
$cut->assertPayload('TestMessage', $data, new JsonSchemaArray($this->schema()), $this->typeSchemaMap());
85+
$this->assertTrue(true);
86+
}
87+
88+
/**
89+
* @test
90+
*/
91+
public function it_throws_json_validation_error_exception(): void
92+
{
93+
$data = $this->validData();
94+
$data['subObject']['p1'] = 'to';
95+
96+
$expectedMessage = <<<'Msg'
97+
Validation of "TestMessage payload" failed: field "subObject.p1" [minLength] {
98+
"min": 3,
99+
"length": 2
100+
}
101+
Msg;
102+
103+
$cut = new OpisJsonSchema();
104+
try {
105+
$cut->assertPayload('TestMessage', $data, new JsonSchemaArray($this->schema()), $this->typeSchemaMap());
106+
} catch (JsonValidationError $e) {
107+
$this->assertSame(400, $e->getCode());
108+
$this->assertStringStartsWith($expectedMessage, $e->getMessage());
109+
}
110+
}
111+
}

0 commit comments

Comments
 (0)