Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: json-schema-interface #1

Merged
merged 5 commits into from
Oct 26, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 31 additions & 6 deletions src/CollectionSchema.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@
/**
* @template I
*
* @phpstan-type CollectionSchemaData array<I>
* @type CollectionSchemaData array<I>
*
* @extends JsonSchema<CollectionSchemaData>
* @implements JsonSchemaInterface<CollectionSchemaData>
*/
abstract class CollectionSchema extends JsonSchema
abstract class CollectionSchema implements JsonSchemaInterface
{
/**
* @param JsonSchema<I> $itemSchema
* @psalm-param JsonSchemaInterface<I> $itemSchema
*/
public function __construct(private JsonSchema $itemSchema)
public function __construct(private JsonSchemaInterface $itemSchema)
{
}

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

public function getDescription(): string
{
return sprintf('Collection of %s', $this->itemSchema->getDescription());
}

protected function getUniqueItems(): ?bool
{
return null;
Expand All @@ -50,7 +55,7 @@ protected function getRange(): ?int
return null;
}

protected function getSchema(): array
public function getSchema(): array
{
$schema = [
'type' => 'array',
Expand All @@ -71,4 +76,24 @@ protected function getSchema(): array

return $schema;
}

/**
* {@inheritdoc}
*/
public function jsonSerialize(): array
{
$schema = $this->getSchema();

/**
* @var array<string, mixed>&array{title: string, description: string, examples: array<T>}
*/
return array_merge(
$schema,
[
'title' => $this->getTitle(),
'description' => $this->getDescription(),
'examples' => [...$this->getExamples()],
],
);
}
}
31 changes: 26 additions & 5 deletions src/EnumSchema.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,45 @@

/**
* @template E
* @extends JsonSchema<E>
*
* @implements JsonSchemaInterface<E>
*/
abstract class EnumSchema extends JsonSchema
abstract class EnumSchema implements JsonSchemaInterface
{
/**
* @return iterable<int, E>
*/
abstract protected function getEnum(): iterable;

public function getExamples(): iterable
{
return $this->getEnum();
}

protected function getSchema(): array
public function getSchema(): array
{
return [
'enum' => [...$this->getEnum()],
];
}

/**
* @return iterable<int, E>
* {@inheritdoc}
*/
abstract protected function getEnum(): iterable;
public function jsonSerialize(): array
{
$schema = $this->getSchema();

/**
* @var array<string, mixed>&array{title: string, description: string, examples: array<T>}
*/
return array_merge(
$schema,
[
'title' => $this->getTitle(),
'description' => $this->getDescription(),
'examples' => [...$this->getExamples()],
],
);
}
}
137 changes: 54 additions & 83 deletions src/JsonSchema.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,54 @@

namespace Knp\JsonSchema;

use Knp\JsonSchema\Validator\Errors;

/**
* @template T of mixed
*
* @implements JsonSchemaInterface<T>
*/
abstract class JsonSchema implements JsonSchemaInterface
class JsonSchema implements JsonSchemaInterface
{
private function __construct(
protected readonly string $title,
protected readonly string $description,
protected readonly iterable $examples,
protected readonly array $schema
) {
}

public function getTitle(): string
{
return $this->title;
}

public function getDescription(): string
{
return $this->description;
}

public function getExamples(): iterable
{
yield from $this->examples;
}

public function getSchema(): array
{
return $this->schema;
}

/**
* @param JsonSchema<E> $schema
* @template E of mixed
* @param JsonSchemaInterface<E> $schema
*
* @return JsonSchema<null|E>
*/
public static function nullable(self $schema): self
public static function nullable(JsonSchemaInterface $schema): self
{
return self::create(
'',
'',
sprintf('Nullable<%s>', $schema->getTitle()),
$schema->getDescription(),
[...$schema->getExamples(), null],
['oneOf' => [self::null(), $schema->jsonSerialize()]],
);
Expand All @@ -36,64 +68,23 @@ public static function create(
string $title,
string $description,
iterable $examples,
$schema
array $schema
): self {
return new class($title, $description, $examples, $schema) extends JsonSchema {
/**
* @var iterable<int, E>
*/
private iterable $examples;

/**
* @param iterable<int, E> $examples
* @param array<string, mixed> $schema
*/
public function __construct(
private string $title,
private string $description,
iterable $examples,
private $schema
) {
$this->examples = [...$examples];
}

public function getTitle(): string
{
return $this->title;
}

public function getDescription(): string
{
return $this->description;
}

/**
* @return iterable<int, E>
*/
public function getExamples(): iterable
{
yield from $this->examples;
}

public function getSchema(): array
{
return $this->schema;
}
};
return new self($title, $description, $examples, $schema);
}

/**
* @template I
*
* @param JsonSchema<I> $jsonSchema
* @param JsonSchemaInterface<I> $jsonSchema
*
* @return JsonSchema<array<int, I>>
*/
public static function collection(self $jsonSchema): self
public static function collection(JsonSchemaInterface $jsonSchema): self
{
return self::create(
sprintf('Collection<%s>', $jsonSchema->getTitle()),
'',
$jsonSchema->getDescription(),
[[...$jsonSchema->getExamples()]],
[
'type' => 'array',
Expand All @@ -103,9 +94,9 @@ public static function collection(self $jsonSchema): self
}

/**
* @return array<string, mixed>&array{title: string, description: string, examples: array<T>}
* {@inheritdoc}
*/
public function jsonSerialize(): mixed
public function jsonSerialize(): array
{
$schema = $this->getSchema();

Expand All @@ -122,27 +113,12 @@ public function jsonSerialize(): mixed
);
}

/**
* @return iterable<int, T>
*/
abstract public function getExamples(): iterable;

public function getTitle(): string
{
return '';
}

public function getDescription(): string
{
return '';
}

/**
* @param scalar $value
*
* @return array<string, mixed>
*/
protected static function constant($value): array
public static function constant($value): array
{
return [
'const' => $value,
Expand All @@ -152,7 +128,7 @@ protected static function constant($value): array
/**
* @return array<string, mixed>
*/
protected static function null(): array
public static function null(): array
{
return [
'type' => 'null',
Expand All @@ -162,7 +138,7 @@ protected static function null(): array
/**
* @return array<string, mixed>
*/
protected static function text(): array
public static function text(): array
{
return [
'type' => 'string',
Expand All @@ -173,7 +149,7 @@ protected static function text(): array
/**
* @return array<string, mixed>
*/
protected static function boolean(): array
public static function boolean(): array
{
return [
'type' => 'boolean',
Expand All @@ -183,7 +159,7 @@ protected static function boolean(): array
/**
* @return array<string, mixed>
*/
protected static function string(?string $format = null): array
public static function string(?string $format = null): array
{
$result = [
...self::text(),
Expand All @@ -200,7 +176,7 @@ protected static function string(?string $format = null): array
/**
* @return array<string, mixed>
*/
protected static function integer(): array
public static function integer(): array
{
return [
'type' => 'integer',
Expand All @@ -210,7 +186,7 @@ protected static function integer(): array
/**
* @return array<string, mixed>
*/
protected static function number(): array
public static function number(): array
{
return [
'type' => 'number',
Expand All @@ -220,7 +196,7 @@ protected static function number(): array
/**
* @return array<string, mixed>
*/
protected static function date(): array
public static function date(): array
{
return [
'type' => 'string',
Expand All @@ -231,7 +207,7 @@ protected static function date(): array
/**
* @return array<string, mixed>
*/
protected static function positiveInteger(): array
public static function positiveInteger(): array
{
return [
...self::integer(),
Expand All @@ -244,15 +220,10 @@ protected static function positiveInteger(): array
*
* @return array{oneOf: array<array<string, mixed>>}
*/
protected static function oneOf(...$schemas): array
public static function oneOf(...$schemas): array
{
return [
'oneOf' => $schemas,
];
}

/**
* @return array<string, mixed>
*/
abstract protected function getSchema(): array;
}
Loading