-
-
Notifications
You must be signed in to change notification settings - Fork 933
fix(jsonschema/jsonld): make @id
and @type
properties required only in the JSON-LD schema for output
#7397
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
base: 4.2
Are you sure you want to change the base?
Conversation
6ea2a72
to
ff5e438
Compare
Interesting, but its possible when using JSON-LD to have |
I see. If so, when using JSON-LD, Would it be ok to modify this PR like that? |
834d183
to
638ad92
Compare
like this. (Just a PoC, don't merge yet.) |
Nice this looks fine! Can the |
@id
and @type
properties required only in the JSON-LD schema for output
@soyuka I fixed in 479f46b and updated the PR title and description. Example of output result![]() ![]() openapi.json{
"openapi": "3.1.0",
"info": {
"title": "Hello API Platform",
"description": "",
"version": "1.0.0"
},
"servers": [
{
"url": "/",
"description": ""
}
],
"paths": {
"/api/books": {
"get": {
"operationId": "api_books_get_collection",
"tags": [
"Book"
],
"responses": {
"200": {
"description": "Book collection",
"content": {
"application/ld+json": {
"schema": {
"type": "object",
"description": "Book.jsonld collection.",
"allOf": [
{
"$ref": "#/components/schemas/HydraCollectionBaseSchema"
},
{
"type": "object",
"properties": {
"hydra:member": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Book.jsonld"
}
}
}
}
]
}
}
}
}
},
"summary": "Retrieves the collection of Book resources.",
"description": "Retrieves the collection of Book resources.",
"parameters": [
{
"name": "page",
"in": "query",
"description": "The collection page number",
"required": false,
"deprecated": false,
"schema": {
"type": "integer",
"default": 1
},
"style": "form",
"explode": false
}
]
},
"post": {
"operationId": "api_books_post",
"tags": [
"Book"
],
"responses": {
"201": {
"description": "Book resource created",
"content": {
"application/ld+json": {
"schema": {
"$ref": "#/components/schemas/Book.jsonld"
}
}
},
"links": {}
},
"400": {
"description": "Invalid input",
"content": {
"application/ld+json": {
"schema": {
"$ref": "#/components/schemas/Error.jsonld"
}
},
"application/problem+json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
},
"links": {}
},
"422": {
"description": "An error occurred",
"content": {
"application/ld+json": {
"schema": {
"$ref": "#/components/schemas/ConstraintViolation.jsonld"
}
},
"application/problem+json": {
"schema": {
"$ref": "#/components/schemas/ConstraintViolation"
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/ConstraintViolation"
}
}
},
"links": {}
}
},
"summary": "Creates a Book resource.",
"description": "Creates a Book resource.",
"parameters": [],
"requestBody": {
"description": "The new Book resource",
"content": {
"application/ld+json": {
"schema": {
"$ref": "#/components/schemas/Book.jsonld.input"
}
}
},
"required": true
}
}
},
"/api/books/{id}": {
"get": {
"operationId": "api_books_id_get",
"tags": [
"Book"
],
"responses": {
"200": {
"description": "Book resource",
"content": {
"application/ld+json": {
"schema": {
"$ref": "#/components/schemas/Book.jsonld"
}
}
}
},
"404": {
"description": "Not found",
"content": {
"application/ld+json": {
"schema": {
"$ref": "#/components/schemas/Error.jsonld"
}
},
"application/problem+json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
},
"links": {}
}
},
"summary": "Retrieves a Book resource.",
"description": "Retrieves a Book resource.",
"parameters": [
{
"name": "id",
"in": "path",
"description": "Book identifier",
"required": true,
"deprecated": false,
"schema": {
"type": "string"
},
"style": "simple",
"explode": false
}
]
},
"delete": {
"operationId": "api_books_id_delete",
"tags": [
"Book"
],
"responses": {
"204": {
"description": "Book resource deleted"
},
"404": {
"description": "Not found",
"content": {
"application/ld+json": {
"schema": {
"$ref": "#/components/schemas/Error.jsonld"
}
},
"application/problem+json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
},
"links": {}
}
},
"summary": "Removes the Book resource.",
"description": "Removes the Book resource.",
"parameters": [
{
"name": "id",
"in": "path",
"description": "Book identifier",
"required": true,
"deprecated": false,
"schema": {
"type": "string"
},
"style": "simple",
"explode": false
}
]
},
"patch": {
"operationId": "api_books_id_patch",
"tags": [
"Book"
],
"responses": {
"200": {
"description": "Book resource updated",
"content": {
"application/ld+json": {
"schema": {
"$ref": "#/components/schemas/Book.jsonld"
}
}
},
"links": {}
},
"400": {
"description": "Invalid input",
"content": {
"application/ld+json": {
"schema": {
"$ref": "#/components/schemas/Error.jsonld"
}
},
"application/problem+json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
},
"links": {}
},
"422": {
"description": "An error occurred",
"content": {
"application/ld+json": {
"schema": {
"$ref": "#/components/schemas/ConstraintViolation.jsonld"
}
},
"application/problem+json": {
"schema": {
"$ref": "#/components/schemas/ConstraintViolation"
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/ConstraintViolation"
}
}
},
"links": {}
},
"404": {
"description": "Not found",
"content": {
"application/ld+json": {
"schema": {
"$ref": "#/components/schemas/Error.jsonld"
}
},
"application/problem+json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
},
"links": {}
}
},
"summary": "Updates the Book resource.",
"description": "Updates the Book resource.",
"parameters": [
{
"name": "id",
"in": "path",
"description": "Book identifier",
"required": true,
"deprecated": false,
"schema": {
"type": "string"
},
"style": "simple",
"explode": false
}
],
"requestBody": {
"description": "The updated Book resource",
"content": {
"application/merge-patch+json": {
"schema": {
"$ref": "#/components/schemas/Book"
}
}
},
"required": true
}
}
}
},
"components": {
"schemas": {
"Book": {
"type": "object",
"properties": {
"id": {
"readOnly": true,
"type": "integer"
},
"title": {
"type": "string"
}
},
"required": [
"title"
]
},
"Book.jsonld": {
"allOf": [
{
"$ref": "#/components/schemas/HydraOutputBaseSchema"
},
{
"$ref": "#/components/schemas/Book"
}
]
},
"Book.jsonld.input": {
"allOf": [
{
"$ref": "#/components/schemas/HydraItemBaseSchema"
},
{
"$ref": "#/components/schemas/Book"
}
]
},
"ConstraintViolation": {
"type": "object",
"description": "Unprocessable entity",
"properties": {
"status": {
"default": 422,
"type": "integer"
},
"violations": {
"type": "array",
"items": {
"type": "object",
"properties": {
"propertyPath": {
"type": "string",
"description": "The property path of the violation"
},
"message": {
"type": "string",
"description": "The message associated with the violation"
}
}
}
},
"detail": {
"readOnly": true,
"type": "string"
},
"type": {
"readOnly": true,
"type": "string"
},
"title": {
"readOnly": true,
"type": [
"string",
"null"
]
},
"instance": {
"readOnly": true,
"type": [
"string",
"null"
]
}
}
},
"ConstraintViolation.jsonld": {
"allOf": [
{
"$ref": "#/components/schemas/HydraOutputBaseSchema"
},
{
"$ref": "#/components/schemas/ConstraintViolation"
}
]
},
"Error": {
"type": "object",
"description": "A representation of common errors.",
"properties": {
"title": {
"readOnly": true,
"description": "A short, human-readable summary of the problem.",
"type": "string"
},
"detail": {
"readOnly": true,
"description": "A human-readable explanation specific to this occurrence of the problem.",
"type": "string"
},
"status": {
"type": "number",
"examples": [
404
],
"default": 400
},
"instance": {
"readOnly": true,
"description": "A URI reference that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced.",
"type": [
"string",
"null"
]
},
"type": {
"readOnly": true,
"description": "A URI reference that identifies the problem type",
"type": "string"
}
}
},
"Error.jsonld": {
"allOf": [
{
"$ref": "#/components/schemas/HydraOutputBaseSchema"
},
{
"$ref": "#/components/schemas/Error"
}
]
},
"HydraCollectionBaseSchema": {
"type": "object",
"required": [
"hydra:member"
],
"properties": {
"hydra:member": {
"type": "array"
},
"hydra:totalItems": {
"type": "integer",
"minimum": 0
},
"hydra:view": {
"type": "object",
"properties": {
"@id": {
"type": "string",
"format": "iri-reference"
},
"@type": {
"type": "string"
},
"hydra:first": {
"type": "string",
"format": "iri-reference"
},
"hydra:last": {
"type": "string",
"format": "iri-reference"
},
"hydra:previous": {
"type": "string",
"format": "iri-reference"
},
"hydra:next": {
"type": "string",
"format": "iri-reference"
}
},
"example": {
"@id": "string",
"type": "string",
"hydra:first": "string",
"hydra:last": "string",
"hydra:previous": "string",
"hydra:next": "string"
}
},
"hydra:search": {
"type": "object",
"properties": {
"@type": {
"type": "string"
},
"hydra:template": {
"type": "string"
},
"hydra:variableRepresentation": {
"type": "string"
},
"hydra:mapping": {
"type": "array",
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string"
},
"variable": {
"type": "string"
},
"property": {
"type": [
"string",
"null"
]
},
"required": {
"type": "boolean"
}
}
}
}
}
}
}
},
"HydraItemBaseSchema": {
"type": "object",
"properties": {
"@context": {
"oneOf": [
{
"type": "string"
},
{
"type": "object",
"properties": {
"@vocab": {
"type": "string"
},
"hydra": {
"type": "string",
"enum": [
"http://www.w3.org/ns/hydra/core#"
]
}
},
"required": [
"@vocab",
"hydra"
],
"additionalProperties": true
}
]
},
"@id": {
"type": "string"
},
"@type": {
"type": "string"
}
}
},
"HydraOutputBaseSchema": {
"required": [
"@id",
"@type"
],
"type": "object",
"properties": {
"@context": {
"oneOf": [
{
"type": "string"
},
{
"type": "object",
"properties": {
"@vocab": {
"type": "string"
},
"hydra": {
"type": "string",
"enum": [
"http://www.w3.org/ns/hydra/core#"
]
}
},
"required": [
"@vocab",
"hydra"
],
"additionalProperties": true
}
]
},
"@id": {
"type": "string"
},
"@type": {
"type": "string"
}
}
}
},
"responses": {},
"parameters": {},
"examples": {},
"requestBodies": {},
"headers": {},
"securitySchemes": {}
},
"security": [],
"tags": [
{
"name": "Book",
"description": "Resource 'Book' operations."
}
],
"webhooks": {}
} Reproducer |
I'm still working to fix the CI error. |
1cda6cf
to
5fdaa77
Compare
I can take a look if you want, and I may move this test to phpunit I thought that keeping |
cb98a29
to
b0cac3a
Compare
$definitionName .= '.input'; | ||
} | ||
|
||
$jsonSchema = $this->schemaFactory->buildSchema($className, 'json', $type, $operation, new Schema(version: $schema->getVersion()), $serializerContext, $forceCollection); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this doesn't work as references will be with json
instead of jsonld
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@soyuka What do you mean?🤔 I understand that the intention of your fix in #6960 was to reference a json schema in the definition of a jsonld schema. I completely agree with that intention, but unfortunately #6960 had the following bugs:
- The output schema was applied even on input, making
@id
and@type
required. - The json schema was not referenced (only
HydraItemBaseSchema
andHydraCollectionBaseSchema
were referenced).
This PR fixes these two bugs.
In order to reference or embed a json schema (e.g., Book
instead of Book.jsonld
), I believe you need to explicitly create a json schema here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But then relations references are not correct anymore
There was a problem hiding this comment.
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 understand what you're saying. Could you please explain in more detail? 🙇♂️
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use:
php -d memory_limit=-1 tests/Fixtures/app/console api:json-schema:generate 'ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue5501\BrokenDocs' --format=jsonld --type=output --operation=_api_/broken_docs/{id}{._format}_get
The current output:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$ref": "#/definitions/BrokenDocs.jsonld-location.read_collection",
"definitions": {
"BrokenDocs.jsonld-location.read_collection": {
"allOf": [
{
"$ref": "#/definitions/HydraItemBaseSchema"
},
{
"type": "object",
"properties": {
"locations": {
"type": "array",
"items": {
"$ref": "#/definitions/Related.jsonld-location.read_collection"
}
}
}
}
]
},
"Related.jsonld-location.read_collection": {
"allOf": [
{
"$ref": "#/definitions/HydraItemBaseSchema"
},
{
"type": "object",
"properties": {
"name": {
"type": [
"string",
"null"
]
}
}
}
]
},
"HydraItemBaseSchema": {
"required": [
"@id",
"@type"
],
"type": "object",
"properties": {
"@context": {
"oneOf": [
{
"type": "string"
},
{
"type": "object",
"properties": {
"@vocab": {
"type": "string"
},
"hydra": {
"type": "string",
"enum": [
"http://www.w3.org/ns/hydra/core#"
]
}
},
"required": [
"@vocab",
"hydra"
],
"additionalProperties": true
}
]
},
"@id": {
"type": "string"
},
"@type": {
"type": "string"
}
}
}
}
}
With this PR:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$ref": "#/definitions/BrokenDocs.jsonld-location.read_collection",
"definitions": {
"BrokenDocs.jsonld-location.read_collection": {
"allOf": [
{
"$ref": "#/definitions/HydraOutputBaseSchema"
},
{
"type": "object",
"properties": {
"locations": {
"type": "array",
"items": {
"$ref": "#/definitions/Related-location.read_collection"
}
}
}
}
]
},
"Related.jsonld-location.read_collection": {
"allOf": [
{
"$ref": "#/definitions/HydraOutputBaseSchema"
},
{
"type": "object",
"properties": {
"name": {
"type": [
"string",
"null"
]
}
}
}
]
},
"HydraOutputBaseSchema": {
"required": [
"@id",
"@type"
],
"type": "object",
"properties": {
"@context": {
"oneOf": [
{
"type": "string"
},
{
"type": "object",
"properties": {
"@vocab": {
"type": "string"
},
"hydra": {
"type": "string",
"enum": [
"http://www.w3.org/ns/hydra/core#"
]
}
},
"required": [
"@vocab",
"hydra"
],
"additionalProperties": true
}
]
},
"@id": {
"type": "string"
},
"@type": {
"type": "string"
}
}
}
}
}
See the $ref should target the jsonld relation not the normal one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@soyuka Thank you for the details! I understand now.
It's true that the problem is that there is no definition of Related-location.read_collection
in this JSON schema for "$ref": "#/definitions/Related-location.read_collection"
.
I tried to fix it with 69d0851.
php -d memory_limit=-1 tests/Fixtures/app/console api:json-schema:generate 'ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue5501\BrokenDocs' --format=jsonld --type=output --operation=_api_/broken_docs/{id}{._format}_get
The new output for this is as follows:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$ref": "#/definitions/BrokenDocs.jsonld-location.read_collection",
"definitions": {
"BrokenDocs.jsonld-location.read_collection": {
"allOf": [
{
"$ref": "#/definitions/HydraOutputBaseSchema"
},
{
"$ref": "#/definitions/BrokenDocs-location.read_collection"
}
]
},
"Related.jsonld-location.read_collection": {
"allOf": [
{
"$ref": "#/definitions/HydraOutputBaseSchema"
},
{
"$ref": "#/definitions/Related-location.read_collection"
}
]
},
"HydraOutputBaseSchema": {
"required": [
"@id",
"@type"
],
"type": "object",
"properties": {
"@context": {
"oneOf": [
{
"type": "string"
},
{
"type": "object",
"properties": {
"@vocab": {
"type": "string"
},
"hydra": {
"type": "string",
"enum": [
"http://www.w3.org/ns/hydra/core#"
]
}
},
"required": [
"@vocab",
"hydra"
],
"additionalProperties": true
}
]
},
"@id": {
"type": "string"
},
"@type": {
"type": "string"
}
}
},
"Related-location.read_collection": {
"type": "object",
"properties": {
"name": {
"type": [
"string",
"null"
]
}
}
},
"BrokenDocs-location.read_collection": {
"type": "object",
"properties": {
"locations": {
"type": "array",
"items": {
"$ref": "#/definitions/Related-location.read_collection"
}
}
}
}
}
}
Also, the openapi.json
of https://github.com/ttskch/api-platform-core-7397 is as follows:
{
"openapi": "3.1.0",
"info": {
"title": "Hello API Platform",
"description": "",
"version": "1.0.0"
},
"servers": [
{
"url": "/",
"description": ""
}
],
"paths": {
"/api/books": {
"get": {
"operationId": "api_books_get_collection",
"tags": [
"Book"
],
"responses": {
"200": {
"description": "Book collection",
"content": {
"application/ld+json": {
"schema": {
"type": "object",
"description": "Book.jsonld collection.",
"allOf": [
{
"$ref": "#/components/schemas/HydraCollectionBaseSchema"
},
{
"type": "object",
"properties": {
"hydra:member": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Book.jsonld"
}
}
}
}
]
}
}
}
}
},
"summary": "Retrieves the collection of Book resources.",
"description": "Retrieves the collection of Book resources.",
"parameters": [
{
"name": "page",
"in": "query",
"description": "The collection page number",
"required": false,
"deprecated": false,
"schema": {
"type": "integer",
"default": 1
},
"style": "form",
"explode": false
}
]
},
"post": {
"operationId": "api_books_post",
"tags": [
"Book"
],
"responses": {
"201": {
"description": "Book resource created",
"content": {
"application/ld+json": {
"schema": {
"$ref": "#/components/schemas/Book.jsonld"
}
}
},
"links": {}
},
"400": {
"description": "Invalid input",
"content": {
"application/ld+json": {
"schema": {
"$ref": "#/components/schemas/Error.jsonld"
}
},
"application/problem+json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
},
"links": {}
},
"422": {
"description": "An error occurred",
"content": {
"application/ld+json": {
"schema": {
"$ref": "#/components/schemas/ConstraintViolation.jsonld"
}
},
"application/problem+json": {
"schema": {
"$ref": "#/components/schemas/ConstraintViolation"
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/ConstraintViolation"
}
}
},
"links": {}
}
},
"summary": "Creates a Book resource.",
"description": "Creates a Book resource.",
"parameters": [],
"requestBody": {
"description": "The new Book resource",
"content": {
"application/ld+json": {
"schema": {
"$ref": "#/components/schemas/Book.jsonld.input"
}
}
},
"required": true
}
}
},
"/api/books/{id}": {
"get": {
"operationId": "api_books_id_get",
"tags": [
"Book"
],
"responses": {
"200": {
"description": "Book resource",
"content": {
"application/ld+json": {
"schema": {
"$ref": "#/components/schemas/Book.jsonld"
}
}
}
},
"404": {
"description": "Not found",
"content": {
"application/ld+json": {
"schema": {
"$ref": "#/components/schemas/Error.jsonld"
}
},
"application/problem+json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
},
"links": {}
}
},
"summary": "Retrieves a Book resource.",
"description": "Retrieves a Book resource.",
"parameters": [
{
"name": "id",
"in": "path",
"description": "Book identifier",
"required": true,
"deprecated": false,
"schema": {
"type": "string"
},
"style": "simple",
"explode": false
}
]
},
"delete": {
"operationId": "api_books_id_delete",
"tags": [
"Book"
],
"responses": {
"204": {
"description": "Book resource deleted"
},
"404": {
"description": "Not found",
"content": {
"application/ld+json": {
"schema": {
"$ref": "#/components/schemas/Error.jsonld"
}
},
"application/problem+json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
},
"links": {}
}
},
"summary": "Removes the Book resource.",
"description": "Removes the Book resource.",
"parameters": [
{
"name": "id",
"in": "path",
"description": "Book identifier",
"required": true,
"deprecated": false,
"schema": {
"type": "string"
},
"style": "simple",
"explode": false
}
]
},
"patch": {
"operationId": "api_books_id_patch",
"tags": [
"Book"
],
"responses": {
"200": {
"description": "Book resource updated",
"content": {
"application/ld+json": {
"schema": {
"$ref": "#/components/schemas/Book.jsonld"
}
}
},
"links": {}
},
"400": {
"description": "Invalid input",
"content": {
"application/ld+json": {
"schema": {
"$ref": "#/components/schemas/Error.jsonld"
}
},
"application/problem+json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
},
"links": {}
},
"422": {
"description": "An error occurred",
"content": {
"application/ld+json": {
"schema": {
"$ref": "#/components/schemas/ConstraintViolation.jsonld"
}
},
"application/problem+json": {
"schema": {
"$ref": "#/components/schemas/ConstraintViolation"
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/ConstraintViolation"
}
}
},
"links": {}
},
"404": {
"description": "Not found",
"content": {
"application/ld+json": {
"schema": {
"$ref": "#/components/schemas/Error.jsonld"
}
},
"application/problem+json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
},
"links": {}
}
},
"summary": "Updates the Book resource.",
"description": "Updates the Book resource.",
"parameters": [
{
"name": "id",
"in": "path",
"description": "Book identifier",
"required": true,
"deprecated": false,
"schema": {
"type": "string"
},
"style": "simple",
"explode": false
}
],
"requestBody": {
"description": "The updated Book resource",
"content": {
"application/merge-patch+json": {
"schema": {
"$ref": "#/components/schemas/Book"
}
}
},
"required": true
}
}
}
},
"components": {
"schemas": {
"Book": {
"type": "object",
"properties": {
"id": {
"readOnly": true,
"type": "integer"
},
"title": {
"type": "string"
}
},
"required": [
"title"
]
},
"Book.jsonld": {
"allOf": [
{
"$ref": "#/components/schemas/HydraOutputBaseSchema"
},
{
"$ref": "#/components/schemas/Book"
}
]
},
"Book.jsonld.input": {
"allOf": [
{
"$ref": "#/components/schemas/HydraItemBaseSchema"
},
{
"$ref": "#/components/schemas/Book"
}
]
},
"ConstraintViolation": {
"type": "object",
"description": "Unprocessable entity",
"properties": {
"status": {
"default": 422,
"type": "integer"
},
"violations": {
"type": "array",
"items": {
"type": "object",
"properties": {
"propertyPath": {
"type": "string",
"description": "The property path of the violation"
},
"message": {
"type": "string",
"description": "The message associated with the violation"
}
}
}
},
"detail": {
"readOnly": true,
"type": "string"
},
"description": {
"readOnly": true,
"type": "string"
},
"type": {
"readOnly": true,
"type": "string"
},
"title": {
"readOnly": true,
"type": [
"string",
"null"
]
},
"instance": {
"readOnly": true,
"type": [
"string",
"null"
]
}
}
},
"ConstraintViolation.jsonld": {
"allOf": [
{
"$ref": "#/components/schemas/HydraOutputBaseSchema"
},
{
"$ref": "#/components/schemas/ConstraintViolation"
}
],
"description": "Unprocessable entity"
},
"Error": {
"type": "object",
"description": "A representation of common errors.",
"properties": {
"title": {
"readOnly": true,
"description": "A short, human-readable summary of the problem.",
"type": "string"
},
"detail": {
"readOnly": true,
"description": "A human-readable explanation specific to this occurrence of the problem.",
"type": "string"
},
"status": {
"type": "number",
"examples": [
404
],
"default": 400
},
"instance": {
"readOnly": true,
"description": "A URI reference that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced.",
"type": [
"string",
"null"
]
},
"type": {
"readOnly": true,
"description": "A URI reference that identifies the problem type",
"type": "string"
},
"description": {
"readOnly": true,
"type": [
"string",
"null"
]
}
}
},
"Error.jsonld": {
"allOf": [
{
"$ref": "#/components/schemas/HydraOutputBaseSchema"
},
{
"$ref": "#/components/schemas/Error"
}
],
"description": "A representation of common errors."
},
"HydraCollectionBaseSchema": {
"type": "object",
"required": [
"hydra:member"
],
"properties": {
"hydra:member": {
"type": "array"
},
"hydra:totalItems": {
"type": "integer",
"minimum": 0
},
"hydra:view": {
"type": "object",
"properties": {
"@id": {
"type": "string",
"format": "iri-reference"
},
"@type": {
"type": "string"
},
"hydra:first": {
"type": "string",
"format": "iri-reference"
},
"hydra:last": {
"type": "string",
"format": "iri-reference"
},
"hydra:previous": {
"type": "string",
"format": "iri-reference"
},
"hydra:next": {
"type": "string",
"format": "iri-reference"
}
},
"example": {
"@id": "string",
"type": "string",
"hydra:first": "string",
"hydra:last": "string",
"hydra:previous": "string",
"hydra:next": "string"
}
},
"hydra:search": {
"type": "object",
"properties": {
"@type": {
"type": "string"
},
"hydra:template": {
"type": "string"
},
"hydra:variableRepresentation": {
"type": "string"
},
"hydra:mapping": {
"type": "array",
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string"
},
"variable": {
"type": "string"
},
"property": {
"type": [
"string",
"null"
]
},
"required": {
"type": "boolean"
}
}
}
}
}
}
}
},
"HydraItemBaseSchema": {
"type": "object",
"properties": {
"@context": {
"oneOf": [
{
"type": "string"
},
{
"type": "object",
"properties": {
"@vocab": {
"type": "string"
},
"hydra": {
"type": "string",
"enum": [
"http://www.w3.org/ns/hydra/core#"
]
}
},
"required": [
"@vocab",
"hydra"
],
"additionalProperties": true
}
]
},
"@id": {
"type": "string"
},
"@type": {
"type": "string"
}
}
},
"HydraOutputBaseSchema": {
"required": [
"@id",
"@type"
],
"type": "object",
"properties": {
"@context": {
"oneOf": [
{
"type": "string"
},
{
"type": "object",
"properties": {
"@vocab": {
"type": "string"
},
"hydra": {
"type": "string",
"enum": [
"http://www.w3.org/ns/hydra/core#"
]
}
},
"required": [
"@vocab",
"hydra"
],
"additionalProperties": true
}
]
},
"@id": {
"type": "string"
},
"@type": {
"type": "string"
}
}
}
},
"responses": {},
"parameters": {},
"examples": {},
"requestBodies": {},
"headers": {},
"securitySchemes": {}
},
"security": [],
"tags": [
{
"name": "Book",
"description": "Resource 'Book' operations."
}
],
"webhooks": {}
}
What about this behavior?
If this still causes problems, we'll give up on reusing the json schema within the jsonld schema and revert to the previous behavior for this part.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO it is a really hard problem to fix I spent quite some time in the refactoring trying not to break this :/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see. It's true that this change has a large impact, but the benefits are limited (just the size of openapi.json will be slightly smaller).
Therefore, the idea of reusing JSON Schema will not be included in this PR. Thanks.
b0cac3a
to
5fdaa77
Compare
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) { | ||
if ('jsonld' !== $format) { |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I don't think I understand your intention correctly.
Isn't this an argument that @id
and @context
should be included as optional fields in the JSON-LD input schema?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
exactly !
There was a problem hiding this comment.
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👍
53e1e96
to
fa1305f
Compare
…ferencing it It cannot always be referenced, as there may be resources that don't have a JSON schema but only a JSON-LD schema. It's not certain at the time the JSON-LD schema is being generated whether a JSON schema will ultimately be defined. Therefore, the JSON schema will be referenced only if it's already defined.
fa1305f
to
ad9be8a
Compare
rebased with current 4.2 |
e92aeff
to
d1e60d9
Compare
@soyuka I've mostly revised the existing tests to match the implementation. The only thing I'm unsure of is how to properly modify The new schema uses |
…is always defined
can you check my patch? |
This PR makes
@id
and@type
properties required only in the JSON-LD schema for output.