Skip to content

Commit 095a681

Browse files
author
Antoine Lelaisant
authored
Merge pull request #1 from KnpLabs/fix/json-schema-interface
fix: json-schema-interface
2 parents d250dcb + 61c0b00 commit 095a681

7 files changed

+191
-110
lines changed

src/CollectionSchema.php

+31-6
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,16 @@
77
/**
88
* @template I
99
*
10-
* @phpstan-type CollectionSchemaData array<I>
10+
* @type CollectionSchemaData array<I>
1111
*
12-
* @extends JsonSchema<CollectionSchemaData>
12+
* @implements JsonSchemaInterface<CollectionSchemaData>
1313
*/
14-
abstract class CollectionSchema extends JsonSchema
14+
abstract class CollectionSchema implements JsonSchemaInterface
1515
{
1616
/**
17-
* @param JsonSchema<I> $itemSchema
17+
* @psalm-param JsonSchemaInterface<I> $itemSchema
1818
*/
19-
public function __construct(private JsonSchema $itemSchema)
19+
public function __construct(private JsonSchemaInterface $itemSchema)
2020
{
2121
}
2222

@@ -30,6 +30,11 @@ public function getTitle(): string
3030
return sprintf('Collection<%s>', $this->itemSchema->getTitle());
3131
}
3232

33+
public function getDescription(): string
34+
{
35+
return sprintf('Collection of %s', $this->itemSchema->getDescription());
36+
}
37+
3338
protected function getUniqueItems(): ?bool
3439
{
3540
return null;
@@ -50,7 +55,7 @@ protected function getRange(): ?int
5055
return null;
5156
}
5257

53-
protected function getSchema(): array
58+
public function getSchema(): array
5459
{
5560
$schema = [
5661
'type' => 'array',
@@ -71,4 +76,24 @@ protected function getSchema(): array
7176

7277
return $schema;
7378
}
79+
80+
/**
81+
* {@inheritdoc}
82+
*/
83+
public function jsonSerialize(): array
84+
{
85+
$schema = $this->getSchema();
86+
87+
/**
88+
* @var array<string, mixed>&array{title: string, description: string, examples: array<T>}
89+
*/
90+
return array_merge(
91+
$schema,
92+
[
93+
'title' => $this->getTitle(),
94+
'description' => $this->getDescription(),
95+
'examples' => [...$this->getExamples()],
96+
],
97+
);
98+
}
7499
}

src/EnumSchema.php

+26-5
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,45 @@
66

77
/**
88
* @template E
9-
* @extends JsonSchema<E>
9+
*
10+
* @implements JsonSchemaInterface<E>
1011
*/
11-
abstract class EnumSchema extends JsonSchema
12+
abstract class EnumSchema implements JsonSchemaInterface
1213
{
14+
/**
15+
* @return iterable<int, E>
16+
*/
17+
abstract protected function getEnum(): iterable;
18+
1319
public function getExamples(): iterable
1420
{
1521
return $this->getEnum();
1622
}
1723

18-
protected function getSchema(): array
24+
public function getSchema(): array
1925
{
2026
return [
2127
'enum' => [...$this->getEnum()],
2228
];
2329
}
2430

2531
/**
26-
* @return iterable<int, E>
32+
* {@inheritdoc}
2733
*/
28-
abstract protected function getEnum(): iterable;
34+
public function jsonSerialize(): array
35+
{
36+
$schema = $this->getSchema();
37+
38+
/**
39+
* @var array<string, mixed>&array{title: string, description: string, examples: array<T>}
40+
*/
41+
return array_merge(
42+
$schema,
43+
[
44+
'title' => $this->getTitle(),
45+
'description' => $this->getDescription(),
46+
'examples' => [...$this->getExamples()],
47+
],
48+
);
49+
}
2950
}

src/JsonSchema.php

+54-83
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,54 @@
44

55
namespace Knp\JsonSchema;
66

7+
use Knp\JsonSchema\Validator\Errors;
8+
79
/**
810
* @template T of mixed
11+
*
12+
* @implements JsonSchemaInterface<T>
913
*/
10-
abstract class JsonSchema implements JsonSchemaInterface
14+
class JsonSchema implements JsonSchemaInterface
1115
{
16+
private function __construct(
17+
protected readonly string $title,
18+
protected readonly string $description,
19+
protected readonly iterable $examples,
20+
protected readonly array $schema
21+
) {
22+
}
23+
24+
public function getTitle(): string
25+
{
26+
return $this->title;
27+
}
28+
29+
public function getDescription(): string
30+
{
31+
return $this->description;
32+
}
33+
34+
public function getExamples(): iterable
35+
{
36+
yield from $this->examples;
37+
}
38+
39+
public function getSchema(): array
40+
{
41+
return $this->schema;
42+
}
43+
1244
/**
13-
* @param JsonSchema<E> $schema
1445
* @template E of mixed
46+
* @param JsonSchemaInterface<E> $schema
1547
*
1648
* @return JsonSchema<null|E>
1749
*/
18-
public static function nullable(self $schema): self
50+
public static function nullable(JsonSchemaInterface $schema): self
1951
{
2052
return self::create(
21-
'',
22-
'',
53+
sprintf('Nullable<%s>', $schema->getTitle()),
54+
$schema->getDescription(),
2355
[...$schema->getExamples(), null],
2456
['oneOf' => [self::null(), $schema->jsonSerialize()]],
2557
);
@@ -36,64 +68,23 @@ public static function create(
3668
string $title,
3769
string $description,
3870
iterable $examples,
39-
$schema
71+
array $schema
4072
): self {
41-
return new class($title, $description, $examples, $schema) extends JsonSchema {
42-
/**
43-
* @var iterable<int, E>
44-
*/
45-
private iterable $examples;
46-
47-
/**
48-
* @param iterable<int, E> $examples
49-
* @param array<string, mixed> $schema
50-
*/
51-
public function __construct(
52-
private string $title,
53-
private string $description,
54-
iterable $examples,
55-
private $schema
56-
) {
57-
$this->examples = [...$examples];
58-
}
59-
60-
public function getTitle(): string
61-
{
62-
return $this->title;
63-
}
64-
65-
public function getDescription(): string
66-
{
67-
return $this->description;
68-
}
69-
70-
/**
71-
* @return iterable<int, E>
72-
*/
73-
public function getExamples(): iterable
74-
{
75-
yield from $this->examples;
76-
}
77-
78-
public function getSchema(): array
79-
{
80-
return $this->schema;
81-
}
82-
};
73+
return new self($title, $description, $examples, $schema);
8374
}
8475

8576
/**
8677
* @template I
8778
*
88-
* @param JsonSchema<I> $jsonSchema
79+
* @param JsonSchemaInterface<I> $jsonSchema
8980
*
9081
* @return JsonSchema<array<int, I>>
9182
*/
92-
public static function collection(self $jsonSchema): self
83+
public static function collection(JsonSchemaInterface $jsonSchema): self
9384
{
9485
return self::create(
9586
sprintf('Collection<%s>', $jsonSchema->getTitle()),
96-
'',
87+
$jsonSchema->getDescription(),
9788
[[...$jsonSchema->getExamples()]],
9889
[
9990
'type' => 'array',
@@ -103,9 +94,9 @@ public static function collection(self $jsonSchema): self
10394
}
10495

10596
/**
106-
* @return array<string, mixed>&array{title: string, description: string, examples: array<T>}
97+
* {@inheritdoc}
10798
*/
108-
public function jsonSerialize(): mixed
99+
public function jsonSerialize(): array
109100
{
110101
$schema = $this->getSchema();
111102

@@ -122,27 +113,12 @@ public function jsonSerialize(): mixed
122113
);
123114
}
124115

125-
/**
126-
* @return iterable<int, T>
127-
*/
128-
abstract public function getExamples(): iterable;
129-
130-
public function getTitle(): string
131-
{
132-
return '';
133-
}
134-
135-
public function getDescription(): string
136-
{
137-
return '';
138-
}
139-
140116
/**
141117
* @param scalar $value
142118
*
143119
* @return array<string, mixed>
144120
*/
145-
protected static function constant($value): array
121+
public static function constant($value): array
146122
{
147123
return [
148124
'const' => $value,
@@ -152,7 +128,7 @@ protected static function constant($value): array
152128
/**
153129
* @return array<string, mixed>
154130
*/
155-
protected static function null(): array
131+
public static function null(): array
156132
{
157133
return [
158134
'type' => 'null',
@@ -162,7 +138,7 @@ protected static function null(): array
162138
/**
163139
* @return array<string, mixed>
164140
*/
165-
protected static function text(): array
141+
public static function text(): array
166142
{
167143
return [
168144
'type' => 'string',
@@ -173,7 +149,7 @@ protected static function text(): array
173149
/**
174150
* @return array<string, mixed>
175151
*/
176-
protected static function boolean(): array
152+
public static function boolean(): array
177153
{
178154
return [
179155
'type' => 'boolean',
@@ -183,7 +159,7 @@ protected static function boolean(): array
183159
/**
184160
* @return array<string, mixed>
185161
*/
186-
protected static function string(?string $format = null): array
162+
public static function string(?string $format = null): array
187163
{
188164
$result = [
189165
...self::text(),
@@ -200,7 +176,7 @@ protected static function string(?string $format = null): array
200176
/**
201177
* @return array<string, mixed>
202178
*/
203-
protected static function integer(): array
179+
public static function integer(): array
204180
{
205181
return [
206182
'type' => 'integer',
@@ -210,7 +186,7 @@ protected static function integer(): array
210186
/**
211187
* @return array<string, mixed>
212188
*/
213-
protected static function number(): array
189+
public static function number(): array
214190
{
215191
return [
216192
'type' => 'number',
@@ -220,7 +196,7 @@ protected static function number(): array
220196
/**
221197
* @return array<string, mixed>
222198
*/
223-
protected static function date(): array
199+
public static function date(): array
224200
{
225201
return [
226202
'type' => 'string',
@@ -231,7 +207,7 @@ protected static function date(): array
231207
/**
232208
* @return array<string, mixed>
233209
*/
234-
protected static function positiveInteger(): array
210+
public static function positiveInteger(): array
235211
{
236212
return [
237213
...self::integer(),
@@ -244,15 +220,10 @@ protected static function positiveInteger(): array
244220
*
245221
* @return array{oneOf: array<array<string, mixed>>}
246222
*/
247-
protected static function oneOf(...$schemas): array
223+
public static function oneOf(...$schemas): array
248224
{
249225
return [
250226
'oneOf' => $schemas,
251227
];
252228
}
253-
254-
/**
255-
* @return array<string, mixed>
256-
*/
257-
abstract protected function getSchema(): array;
258229
}

0 commit comments

Comments
 (0)