From 562a3ae011e132793cf5c78394e26a299b9e1664 Mon Sep 17 00:00:00 2001 From: soyuka Date: Mon, 19 Oct 2026 16:36:04 +0200 Subject: [PATCH] fix(jsonapi): describe included items as resource objects included items referenced the related resource's whole document definition ({data: {...}}) while the serializer emits bare resource objects. Move the resource object to its own X.jsonapi.resource definition, referenced by the document's data and by included. --- src/JsonApi/JsonSchema/SchemaFactory.php | 21 +++++---- .../JsonSchema/InputDtoSchemaFactoryTest.php | 6 ++- ...ReservedAttributeNameSchemaFactoryTest.php | 2 +- .../Tests/JsonSchema/SchemaFactoryTest.php | 39 ++++++++-------- .../JsonApi/RelatedResourcesInclusionTest.php | 26 +++++++++++ .../JsonSchema/JsonApiJsonSchemaTest.php | 46 +++++++++---------- .../JsonSchemaExplicitContextTest.php | 3 +- .../Functional/JsonSchema/JsonSchemaTest.php | 25 +++++++++- 8 files changed, 107 insertions(+), 61 deletions(-) diff --git a/src/JsonApi/JsonSchema/SchemaFactory.php b/src/JsonApi/JsonSchema/SchemaFactory.php index 17eca57b4e..7aa8e9ac16 100644 --- a/src/JsonApi/JsonSchema/SchemaFactory.php +++ b/src/JsonApi/JsonSchema/SchemaFactory.php @@ -161,7 +161,7 @@ public function buildSchema(string $className, string $format = 'jsonapi', strin } if (!$collectionKey) { - $definitions[$definitionName]['properties'] = $this->buildDefinitionPropertiesSchema($key, $inputOrOutputClass, $format, $type, $operation, $schema, []); + $definitions[$definitionName]['properties'] = $this->buildDefinitionPropertiesSchema($key, $definitionName, $inputOrOutputClass, $format, $type, $operation, $schema, []); $schema['$ref'] = $prefix.$definitionName; return $schema; @@ -259,7 +259,7 @@ public function buildSchema(string $className, string $format = 'jsonapi', strin unset($schema['items']); unset($schema['type']); - $properties = $this->buildDefinitionPropertiesSchema($key, $inputOrOutputClass, $format, $type, $operation, $schema, []); + $properties = $this->buildDefinitionPropertiesSchema($key, $definitionName, $inputOrOutputClass, $format, $type, $operation, $schema, []); $properties['data'] = [ 'type' => 'array', @@ -282,7 +282,7 @@ public function setSchemaFactory(SchemaFactoryInterface $schemaFactory): void } } - private function buildDefinitionPropertiesSchema(string $key, string $propertyClass, string $format, string $type, ?Operation $operation, Schema $schema, ?array $serializerContext): array + private function buildDefinitionPropertiesSchema(string $key, string $documentDefinitionName, string $propertyClass, string $format, string $type, ?Operation $operation, Schema $schema, ?array $serializerContext): array { // Capture the resource's operation up front; the relationship loop below reassigns $operation. $resourceOperation = $operation; @@ -321,7 +321,7 @@ private function buildDefinitionPropertiesSchema(string $key, string $propertyCl } // keep one entry per related definition: a polymorphic relation targets several resource classes, all of which may appear in "included" foreach (array_keys($refs) as $ref) { - $relatedDefinitions[$ref] = ['$ref' => $ref]; + $relatedDefinitions[$ref.'.resource'] = ['$ref' => $ref.'.resource']; } // A relationship literally named "relationships"/"included" is prefixed at runtime too. $relationshipName = ReservedAttributeNameConverter::JSON_API_RESERVED_ATTRIBUTES[$propertyName] ?? $propertyName; @@ -374,12 +374,15 @@ private function buildDefinitionPropertiesSchema(string $key, string $propertyCl // Only relax the requirement on the input schema; responses still always carry an `id`. $required = Schema::TYPE_INPUT === $type && $resourceOperation instanceof HttpOperation && 'POST' === $resourceOperation->getMethod() ? ['type'] : ['type', 'id']; + $resourceDefinitionName = $documentDefinitionName.'.resource'; + $definitions[$resourceDefinitionName] = [ + 'type' => 'object', + 'properties' => $replacement, + 'required' => $required, + ]; + return [ - 'data' => [ - 'type' => 'object', - 'properties' => $replacement, - 'required' => $required, - ], + 'data' => ['$ref' => $this->getSchemaUriPrefix($schema->getVersion()).$resourceDefinitionName], ] + $included; } diff --git a/src/JsonApi/Tests/JsonSchema/InputDtoSchemaFactoryTest.php b/src/JsonApi/Tests/JsonSchema/InputDtoSchemaFactoryTest.php index 8d04b2b36e..db36847f81 100644 --- a/src/JsonApi/Tests/JsonSchema/InputDtoSchemaFactoryTest.php +++ b/src/JsonApi/Tests/JsonSchema/InputDtoSchemaFactoryTest.php @@ -43,7 +43,8 @@ public function testInputSchemaDocumentsEmbeddedDtoCollectionAsAttribute(): void $schemaFactory = $this->buildSchemaFactory($operation); $schema = $schemaFactory->buildSchema(Order::class, 'jsonapi', Schema::TYPE_INPUT, $operation); - $data = $schema->getDefinitions()[$schema->getRootDefinitionKey()]['properties']['data']; + $this->assertSame(['$ref' => '#/definitions/'.$schema->getRootDefinitionKey().'.resource'], $schema->getDefinitions()[$schema->getRootDefinitionKey()]['properties']['data']); + $data = $schema->getDefinitions()[$schema->getRootDefinitionKey().'.resource']; $this->assertArrayNotHasKey('relationships', $data['properties']); $this->assertEqualsCanonicalizing(['reference', 'lines'], array_keys($data['properties']['attributes']['properties'])); @@ -55,7 +56,8 @@ public function testOutputSchemaKeepsResourceCollectionAsRelationship(): void $schemaFactory = $this->buildSchemaFactory($operation); $schema = $schemaFactory->buildSchema(Order::class, 'jsonapi', Schema::TYPE_OUTPUT, $operation); - $data = $schema->getDefinitions()[$schema->getRootDefinitionKey()]['properties']['data']; + $this->assertSame(['$ref' => '#/definitions/'.$schema->getRootDefinitionKey().'.resource'], $schema->getDefinitions()[$schema->getRootDefinitionKey()]['properties']['data']); + $data = $schema->getDefinitions()[$schema->getRootDefinitionKey().'.resource']; $this->assertArrayHasKey('lines', $data['properties']['relationships']['properties']); $this->assertArrayNotHasKey('lines', $data['properties']['attributes']['properties']); diff --git a/src/JsonApi/Tests/JsonSchema/ReservedAttributeNameSchemaFactoryTest.php b/src/JsonApi/Tests/JsonSchema/ReservedAttributeNameSchemaFactoryTest.php index a1865ab194..46ee4c9c55 100644 --- a/src/JsonApi/Tests/JsonSchema/ReservedAttributeNameSchemaFactoryTest.php +++ b/src/JsonApi/Tests/JsonSchema/ReservedAttributeNameSchemaFactoryTest.php @@ -87,7 +87,7 @@ public function testReservedAttributeNamesAreRenamedLikeTheResponse(): void { $resultSchema = $this->schemaFactory->buildSchema(Dummy::class); $rootDefinitionKey = $resultSchema->getRootDefinitionKey(); - $attributes = $resultSchema['definitions'][$rootDefinitionKey]['properties']['data']['properties']['attributes']['properties']; + $attributes = $resultSchema['definitions'][$rootDefinitionKey.'.resource']['properties']['attributes']['properties']; // Every reserved name must be documented under the prefixed key the ReservedAttributeNameConverter emits. $this->assertArrayHasKey('_id', $attributes); diff --git a/src/JsonApi/Tests/JsonSchema/SchemaFactoryTest.php b/src/JsonApi/Tests/JsonSchema/SchemaFactoryTest.php index 6496f19ffa..3a38b4595f 100644 --- a/src/JsonApi/Tests/JsonSchema/SchemaFactoryTest.php +++ b/src/JsonApi/Tests/JsonSchema/SchemaFactoryTest.php @@ -107,7 +107,7 @@ public function testHasRootDefinitionKeyBuildSchema(): void $this->assertTrue(isset($definitions[$rootDefinitionKey])); $this->assertTrue(isset($definitions[$rootDefinitionKey]['properties'])); $properties = $resultSchema['definitions'][$rootDefinitionKey]['properties']; - $this->assertArrayHasKey('data', $properties); + $this->assertSame(['$ref' => '#/definitions/'.$rootDefinitionKey.'.resource'], $properties['data']); $this->assertEquals( [ 'type' => 'object', @@ -128,7 +128,7 @@ public function testHasRootDefinitionKeyBuildSchema(): void 'id', ], ], - $properties['data'] + $definitions[$rootDefinitionKey.'.resource'] ); } @@ -162,16 +162,13 @@ public function testSchemaTypeBuildSchema(): void $objectSchema = $resultSchema['allOf'][1]; $this->assertArrayHasKey('data', $objectSchema['properties']); - $this->assertArrayHasKey('items', $objectSchema['properties']['data']); - $this->assertArrayNotHasKey('$ref', $objectSchema['properties']['data']['items']['properties']['attributes']); - $this->assertSame('object', $objectSchema['properties']['data']['items']['properties']['attributes']['type']); + $this->assertSame(['$ref' => '#/definitions/Dummy.jsonapi.resource'], $objectSchema['properties']['data']['items']); - $properties = $objectSchema['properties']; - $this->assertArrayHasKey('data', $properties); - $this->assertArrayHasKey('items', $properties['data']); - $this->assertArrayHasKey('id', $properties['data']['items']['properties']); - $this->assertArrayHasKey('type', $properties['data']['items']['properties']); - $this->assertArrayHasKey('attributes', $properties['data']['items']['properties']); + $resource = $resultSchema['definitions']['Dummy.jsonapi.resource']; + $this->assertArrayNotHasKey('$ref', $resource['properties']['attributes']); + $this->assertSame('object', $resource['properties']['attributes']['type']); + $this->assertArrayHasKey('id', $resource['properties']); + $this->assertArrayHasKey('type', $resource['properties']); $forcedCollection = $this->schemaFactory->buildSchema(Dummy::class, 'jsonapi', Schema::TYPE_OUTPUT, forceCollection: true); $this->assertEquals($resultSchema['allOf'][0]['$ref'], $forcedCollection['allOf'][0]['$ref']); @@ -194,8 +191,8 @@ public function testPostInputSchemaDoesNotRequireId(): void $definitions = $resultSchema->getDefinitions(); $rootDefinitionKey = $resultSchema->getRootDefinitionKey(); - $this->assertTrue(isset($definitions[$rootDefinitionKey]['properties']['data'])); - $data = $definitions[$rootDefinitionKey]['properties']['data']; + $this->assertSame(['$ref' => '#/definitions/'.$rootDefinitionKey.'.resource'], $definitions[$rootDefinitionKey]['properties']['data']); + $data = $definitions[$rootDefinitionKey.'.resource']; $this->assertArrayHasKey('required', $data); $this->assertSame(['type'], $data['required']); } @@ -206,7 +203,7 @@ public function testPatchInputSchemaRequiresId(): void $definitions = $resultSchema->getDefinitions(); $rootDefinitionKey = $resultSchema->getRootDefinitionKey(); - $data = $definitions[$rootDefinitionKey]['properties']['data']; + $data = $definitions[$rootDefinitionKey.'.resource']; $this->assertSame(['type', 'id'], $data['required']); } @@ -216,7 +213,7 @@ public function testPostOutputSchemaRequiresId(): void $definitions = $resultSchema->getDefinitions(); $rootDefinitionKey = $resultSchema->getRootDefinitionKey(); - $data = $definitions[$rootDefinitionKey]['properties']['data']; + $data = $definitions[$rootDefinitionKey.'.resource']; $this->assertSame(['type', 'id'], $data['required']); } @@ -227,7 +224,7 @@ public function testRelationIsExcludedFromAttributes(): void $definitions = $resultSchema->getDefinitions(); $rootDefinitionKey = $resultSchema->getRootDefinitionKey(); - $dataProperties = $definitions[$rootDefinitionKey]['properties']['data']['properties']; + $dataProperties = $definitions[$rootDefinitionKey.'.resource']['properties']; $this->assertArrayHasKey('attributes', $dataProperties); $this->assertArrayNotHasKey('$ref', $dataProperties['attributes']); @@ -251,7 +248,7 @@ public function testRelationshipLinkageRequiresTypeAndId(): void $definitions = $resultSchema->getDefinitions(); $rootDefinitionKey = $resultSchema->getRootDefinitionKey(); - $dataProperties = $definitions[$rootDefinitionKey]['properties']['data']['properties']; + $dataProperties = $definitions[$rootDefinitionKey.'.resource']['properties']; // a resource identifier object MUST contain type and id, @see https://jsonapi.org/format/#document-resource-identifier-objects $linkage = $dataProperties['relationships']['properties']['relatedDummy']['properties']['data']['oneOf'][1]; @@ -269,8 +266,8 @@ public function testIncludedListsAllPolymorphicRelationTargets(): void $included = $definitions[$rootDefinitionKey]['properties']['included']; $refs = array_column($included['items']['anyOf'], '$ref'); - $this->assertContains('#/definitions/RelatedDummy.jsonapi', $refs); - $this->assertContains('#/definitions/OtherRelatedDummy.jsonapi', $refs, 'every target of a polymorphic relation must be listed in included'); + $this->assertContains('#/definitions/RelatedDummy.jsonapi.resource', $refs); + $this->assertContains('#/definitions/OtherRelatedDummy.jsonapi.resource', $refs, 'every target of a polymorphic relation must be listed in included'); } public function testIncludedReferencesNotExposedRelatedResource(): void @@ -281,7 +278,7 @@ public function testIncludedReferencesNotExposedRelatedResource(): void $definitions = $resultSchema->getDefinitions(); $included = $definitions[$resultSchema->getRootDefinitionKey()]['properties']['included']; - $this->assertSame([['$ref' => '#/definitions/RelatedDummy.jsonapi']], $included['items']['anyOf']); + $this->assertSame([['$ref' => '#/definitions/RelatedDummy.jsonapi.resource']], $included['items']['anyOf']); $this->assertArrayHasKey('RelatedDummy.jsonapi', $definitions); } @@ -294,7 +291,7 @@ public function testIncludedListsExposedAndNotExposedTargets(): void $included = $definitions[$resultSchema->getRootDefinitionKey()]['properties']['included']; $this->assertEqualsCanonicalizing( - [['$ref' => '#/definitions/RelatedDummy.jsonapi'], ['$ref' => '#/definitions/OtherRelatedDummy.jsonapi']], + [['$ref' => '#/definitions/RelatedDummy.jsonapi.resource'], ['$ref' => '#/definitions/OtherRelatedDummy.jsonapi.resource']], $included['items']['anyOf'] ); } diff --git a/tests/Functional/JsonApi/RelatedResourcesInclusionTest.php b/tests/Functional/JsonApi/RelatedResourcesInclusionTest.php index d91ae5b058..8090a7e11f 100644 --- a/tests/Functional/JsonApi/RelatedResourcesInclusionTest.php +++ b/tests/Functional/JsonApi/RelatedResourcesInclusionTest.php @@ -13,7 +13,9 @@ namespace ApiPlatform\Tests\Functional\JsonApi; +use ApiPlatform\JsonSchema\Schema; use ApiPlatform\Test\ApiTestCase; +use ApiPlatform\Test\Constraint\MatchesJsonSchema; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyGroup; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyProperty; @@ -55,6 +57,30 @@ protected function setUp(): void $this->recreateSchema(self::getResources()); } + public function testIncludedItemsSchemaMatchesRuntimeResourceObject(): void + { + $this->seedDummyPropertyObjects(1); + + $response = self::createClient()->request('GET', '/dummy_properties/1?include=group', [ + 'headers' => ['Accept' => 'application/vnd.api+json'], + ]); + + $this->assertResponseIsSuccessful(); + + $schemaFactory = self::getContainer()->get('api_platform.json_schema.schema_factory'); + $schema = $schemaFactory->buildSchema(DummyProperty::class, 'jsonapi', Schema::TYPE_OUTPUT); + $definitions = $schema->getDefinitions(); + $anyOf = $definitions[$schema->getRootDefinitionKey()]['properties']['included']['items']['anyOf']; + + $this->assertNotEmpty($anyOf); + + $includedSchema = new MatchesJsonSchema(['definitions' => $definitions, 'anyOf' => $anyOf]); + $included = $response->toArray()['included'][0]; + + $this->assertThat($included, $includedSchema); + $this->assertThat(['type' => 1] + $included, $this->logicalNot($includedSchema)); + } + public function testIncludeManyToOneRelation(): void { $this->seedDummyPropertyObjects(3); diff --git a/tests/Functional/JsonSchema/JsonApiJsonSchemaTest.php b/tests/Functional/JsonSchema/JsonApiJsonSchemaTest.php index 1bacff3d23..75df5ede6b 100644 --- a/tests/Functional/JsonSchema/JsonApiJsonSchemaTest.php +++ b/tests/Functional/JsonSchema/JsonApiJsonSchemaTest.php @@ -59,7 +59,8 @@ public function testJsonApi(): void { $speciesSchema = $this->schemaFactory->buildSchema(Issue6317::class, 'jsonapi', Schema::TYPE_OUTPUT); $this->assertEquals('#/definitions/Issue6317.jsonapi', $speciesSchema['$ref']); - $data = $speciesSchema['definitions']['Issue6317.jsonapi']['properties']['data']; + $this->assertSame(['$ref' => '#/definitions/Issue6317.jsonapi.resource'], $speciesSchema['definitions']['Issue6317.jsonapi']['properties']['data']); + $data = $speciesSchema['definitions']['Issue6317.jsonapi.resource']; $this->assertSame('object', $data['type']); $this->assertSame(['type' => 'string'], $data['properties']['id']); $this->assertSame(['type' => 'string'], $data['properties']['type']); @@ -82,40 +83,40 @@ public function testJsonApiIncludesSchemaForQuestion(): void $questionSchema = $this->schemaFactory->buildSchema(Question::class, 'jsonapi', Schema::TYPE_OUTPUT); $json = $questionSchema->getDefinitions(); - $properties = $json['Question.jsonapi']['properties']['data']['properties']; + $properties = $json['Question.jsonapi.resource']['properties']; $included = $json['Question.jsonapi']['properties']['included']; $this->assertArrayHasKey('answer', $properties['relationships']['properties']); $this->assertArrayHasKey('anyOf', $included['items']); $this->assertCount(1, $included['items']['anyOf']); $this->assertArrayHasKey('$ref', $included['items']['anyOf'][0]); - $this->assertSame('#/definitions/Answer.jsonapi', $included['items']['anyOf'][0]['$ref']); + $this->assertSame('#/definitions/Answer.jsonapi.resource', $included['items']['anyOf'][0]['$ref']); } public function testJsonApiIncludesSchemaForAnimalObservation(): void { $animalObservationSchema = $this->schemaFactory->buildSchema(AnimalObservation::class, 'jsonapi', Schema::TYPE_OUTPUT); $json = $animalObservationSchema->getDefinitions(); - $properties = $json['AnimalObservation.jsonapi']['properties']['data']['properties']; + $properties = $json['AnimalObservation.jsonapi.resource']['properties']; $included = $json['AnimalObservation.jsonapi']['properties']['included']; $this->assertArrayHasKey('individuals', $properties['relationships']['properties']); $this->assertArrayHasKey('anyOf', $included['items']); $this->assertCount(1, $included['items']['anyOf']); - $this->assertSame('#/definitions/Animal.jsonapi', $included['items']['anyOf'][0]['$ref']); + $this->assertSame('#/definitions/Animal.jsonapi.resource', $included['items']['anyOf'][0]['$ref']); } public function testJsonApiIncludesSchemaForAnimal(): void { $animalSchema = $this->schemaFactory->buildSchema(Animal::class, 'jsonapi', Schema::TYPE_OUTPUT); $json = $animalSchema->getDefinitions(); - $properties = $json['Animal.jsonapi']['properties']['data']['properties']; + $properties = $json['Animal.jsonapi.resource']['properties']; $included = $json['Animal.jsonapi']['properties']['included']; $this->assertArrayHasKey('species', $properties['relationships']['properties']); $this->assertArrayHasKey('anyOf', $included['items']); $this->assertCount(1, $included['items']['anyOf']); - $this->assertSame('#/definitions/Species.jsonapi', $included['items']['anyOf'][0]['$ref']); + $this->assertSame('#/definitions/Species.jsonapi.resource', $included['items']['anyOf'][0]['$ref']); } public function testJsonApiIncludesSchemaForSpecies(): void @@ -131,24 +132,7 @@ public function testJsonApiIncludesSchemaForSpecies(): void 'properties' => [ 'data' => [ 'type' => 'array', - 'items' => [ - 'type' => 'object', - 'properties' => [ - 'id' => [ - 'type' => 'string', - ], - 'type' => [ - 'type' => 'string', - ], - 'attributes' => [ - 'type' => 'object', - ], - ], - 'required' => [ - 'type', - 'id', - ], - ], + 'items' => ['$ref' => '#/definitions/Species.jsonapi.resource'], ], ], ], @@ -156,5 +140,17 @@ public function testJsonApiIncludesSchemaForSpecies(): void ], $speciesSchema->getArrayCopy() ); + $this->assertArraySubset( + [ + 'type' => 'object', + 'properties' => [ + 'id' => ['type' => 'string'], + 'type' => ['type' => 'string'], + 'attributes' => ['type' => 'object'], + ], + 'required' => ['type', 'id'], + ], + $speciesSchema->getDefinitions()['Species.jsonapi.resource'] + ); } } diff --git a/tests/Functional/JsonSchema/JsonSchemaExplicitContextTest.php b/tests/Functional/JsonSchema/JsonSchemaExplicitContextTest.php index 8a91d85b01..a4d03af181 100644 --- a/tests/Functional/JsonSchema/JsonSchemaExplicitContextTest.php +++ b/tests/Functional/JsonSchema/JsonSchemaExplicitContextTest.php @@ -99,8 +99,7 @@ public function testJsonApiSchemaDisablesSerializerGroupsByDefault(): void $schema = $this->schemaFactory->buildSchema(ReadWriteGroupedItem::class, 'jsonapi', Schema::TYPE_OUTPUT, $operation); $this->assertStringNotContainsString('rw.read', $schema->getRootDefinitionKey()); - $definition = $schema->getDefinitions()[$schema->getRootDefinitionKey()]; - $attributes = $definition['properties']['data']['properties']['attributes']['properties']; + $attributes = $schema->getDefinitions()[$schema->getRootDefinitionKey().'.resource']['properties']['attributes']['properties']; $this->assertArrayHasKey('secretToken', $attributes); $this->assertArrayHasKey('title', $attributes); } diff --git a/tests/Functional/JsonSchema/JsonSchemaTest.php b/tests/Functional/JsonSchema/JsonSchemaTest.php index b371b23cc1..ab2dc89459 100644 --- a/tests/Functional/JsonSchema/JsonSchemaTest.php +++ b/tests/Functional/JsonSchema/JsonSchemaTest.php @@ -146,10 +146,33 @@ public function testJsonApiIncludedReferencesNotExposedResource(): void $included = $schema['definitions'][$schema->getRootDefinitionKey()]['properties']['included']; - $this->assertSame([['$ref' => '#/definitions/AggregateRating.jsonapi']], $included['items']['anyOf']); + $this->assertSame([['$ref' => '#/definitions/AggregateRating.jsonapi.resource']], $included['items']['anyOf']); $this->assertArrayHasKey('AggregateRating.jsonapi', $schema['definitions']); } + public function testJsonApiIncludedItemsAreResourceObjects(): void + { + $schema = $this->schemaFactory->buildSchema(Product::class, 'jsonapi', Schema::TYPE_OUTPUT, $this->operationMetadataFactory->create('_api_/json-stream-products/{code}_get')); + $definitions = $schema->getDefinitions(); + + $anyOf = $definitions[$schema->getRootDefinitionKey()]['properties']['included']['items']['anyOf']; + $this->assertNotEmpty($anyOf); + + foreach ($anyOf as $entry) { + $resolved = $schema->getArrayCopy(); + foreach (explode('/', substr($entry['$ref'], 2)) as $segment) { + $resolved = $resolved[$segment]; + } + + $this->assertArrayHasKey('id', $resolved['properties'], $entry['$ref']); + $this->assertArrayHasKey('type', $resolved['properties'], $entry['$ref']); + $this->assertArrayNotHasKey('data', $resolved['properties'], $entry['$ref']); + + $documentName = substr($entry['$ref'], \strlen('#/definitions/'), -\strlen('.resource')); + $this->assertSame($entry['$ref'], $definitions[$documentName]['properties']['data']['$ref']); + } + } + public function testArraySchemaWithReference(): void { if ('mongodb' === self::getContainer()->getParameter('kernel.environment')) {