Skip to content
Open
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
20 changes: 12 additions & 8 deletions src/Hydra/JsonSchema/SchemaFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ final class SchemaFactory implements SchemaFactoryInterface, SchemaFactoryAwareI
use SchemaUriPrefixTrait;

private const ITEM_BASE_SCHEMA_NAME = 'HydraItemBaseSchema';
private const ITEM_BASE_SCHEMA_OUTPUT_NAME = 'HydraOutputBaseSchema';
private const COLLECTION_BASE_SCHEMA_NAME = 'HydraCollectionBaseSchema';
private const BASE_PROP = [
'type' => 'string',
Expand Down Expand Up @@ -69,11 +68,8 @@ final class SchemaFactory implements SchemaFactoryInterface, SchemaFactoryAwareI
],
],
] + self::BASE_PROPS,
];

private const ITEM_BASE_SCHEMA_OUTPUT = [
'required' => ['@id', '@type'],
] + self::ITEM_BASE_SCHEMA;
];

/**
* @var array<string, true>
Expand Down Expand Up @@ -104,7 +100,15 @@ public function __construct(
*/
public function buildSchema(string $className, string $format = 'jsonld', string $type = Schema::TYPE_OUTPUT, ?Operation $operation = null, ?Schema $schema = null, ?array $serializerContext = null, bool $forceCollection = false): Schema
{
if ('jsonld' !== $format || 'input' === $type) {
// The input schema must not include `@id` or `@type` as required fields, so it should be a pure JSON schema.
// Strictly speaking, it is possible to include `@id` or `@context` in the input,
// but the generated JSON Schema does not include `"additionalProperties": false` by default,
// so it is possible to include `@id` or `@context` in the input even if the input schema is a JSON schema.
if (Schema::TYPE_INPUT === $type) {
$format = 'json';
}

if ('jsonld' !== $format) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm quite unsure about this as when its an input we were going through this path making @id required only on output

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@soyuka If we add 'input' === $type here, this method will not be executed at all during input, and Book.jsonld.input will not be generated.

The @id @type @context properties will be added during both input and output, and @id @type should only be required during output. This control is done here and here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand, this is exactly what we want: input should not have any of the json-ld specific items which is the case right now no?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@soyuka

Sorry, I don't think I understand your intention correctly.

Interesting, but it's possible when using JSON-LD to have @id or @context (though they're not required).

Isn't this an argument that @id and @context should be included as optional fields in the JSON-LD input schema?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indeed but as we don't have "additionalProperties": false it is allowed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@soyuka Ah, I understood!

By default, JSON Schema doesn't include "additionalProperties": false, so even if @id and @context aren't explicitly defined in the input schema, @id and @context can actually be included in the input, right?

If that's the case, then there's no need to create an input schema like Book.jsonld.input in the first place; the input schema can simply be the Book json schema, right?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

exactly !

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@soyuka Got it! I'm fixing the PR accordingly👍

return $this->schemaFactory->buildSchema($className, $format, $type, $operation, $schema, $serializerContext, $forceCollection);
}
if (!$this->isResourceClass($className)) {
Expand Down Expand Up @@ -140,10 +144,10 @@ public function buildSchema(string $className, string $format = 'jsonld', string
return $schema;
}

$baseName = Schema::TYPE_OUTPUT === $type ? self::ITEM_BASE_SCHEMA_NAME : self::ITEM_BASE_SCHEMA_OUTPUT_NAME;
$baseName = self::ITEM_BASE_SCHEMA_NAME;

if (!isset($definitions[$baseName])) {
$definitions[$baseName] = Schema::TYPE_OUTPUT === $type ? self::ITEM_BASE_SCHEMA_OUTPUT : self::ITEM_BASE_SCHEMA;
$definitions[$baseName] = self::ITEM_BASE_SCHEMA;
}

$allOf = new \ArrayObject(['allOf' => [
Expand Down
Loading