diff --git a/src/JsonSchema/Uri/UriRetriever.php b/src/JsonSchema/Uri/UriRetriever.php index 4d52937a..3e9a71c1 100644 --- a/src/JsonSchema/Uri/UriRetriever.php +++ b/src/JsonSchema/Uri/UriRetriever.php @@ -11,6 +11,7 @@ namespace JsonSchema\Uri; +use JsonSchema\DraftIdentifiers; use JsonSchema\Exception\InvalidSchemaMediaTypeException; use JsonSchema\Exception\JsonDecodingException; use JsonSchema\Exception\ResourceNotFoundException; @@ -182,11 +183,17 @@ public function retrieve($uri, $baseUri = null, $translate = true) $jsonSchema = $this->loadSchema($fetchUri); + // Detect dialect from the root schema's $schema keyword before + // resolvePointer() may walk into a sub-schema. + $dialect = isset($jsonSchema->{'$schema'}) ? rtrim($jsonSchema->{'$schema'}, '#') : null; + $usesDollarId = !in_array($dialect, [DraftIdentifiers::DRAFT_3()->withoutFragment(), DraftIdentifiers::DRAFT_4()->withoutFragment()], true); + // Use the JSON pointer if specified $jsonSchema = $this->resolvePointer($jsonSchema, $resolvedUri); if ($jsonSchema instanceof \stdClass) { - $jsonSchema->id = $resolvedUri; + $idKeyword = $usesDollarId ? '$id' : 'id'; + $jsonSchema->{$idKeyword} = $resolvedUri; } return $jsonSchema; diff --git a/tests/Uri/UriRetrieverTest.php b/tests/Uri/UriRetrieverTest.php index e14f2205..cf37d77d 100644 --- a/tests/Uri/UriRetrieverTest.php +++ b/tests/Uri/UriRetrieverTest.php @@ -339,7 +339,59 @@ public function testRetrieveSchemaFromPackage(): void $this->assertNotFalse($schema); // check that the schema was loaded & processed correctly - $this->assertEquals('454f423bd7edddf0bc77af4130ed9161', md5(json_encode($schema))); + $this->assertEquals('object', $schema->type); + $this->assertObjectHasAttribute('$id', $schema); + $this->assertEquals('package://tests/fixtures/foobar.json', $schema->{'$id'}); + } + + public function testRetrieveDraft04SchemaWithFragmentUsesId(): void + { + $retriever = new UriRetriever(); + $schema = $retriever->retrieve('package://tests/fixtures/draft04-schema-with-fragment.json'); + + $this->assertObjectHasAttribute('id', $schema); + $this->assertObjectNotHasAttribute('$id', $schema); + $this->assertEquals('package://tests/fixtures/draft04-schema-with-fragment.json', $schema->id); + } + + public function testRetrieveDraft04SchemaWithoutFragmentUsesId(): void + { + $retriever = new UriRetriever(); + $schema = $retriever->retrieve('package://tests/fixtures/draft04-schema-without-fragment.json'); + + $this->assertObjectHasAttribute('id', $schema); + $this->assertObjectNotHasAttribute('$id', $schema); + $this->assertEquals('package://tests/fixtures/draft04-schema-without-fragment.json', $schema->id); + } + + public function testRetrieveDraft07SchemaWithFragmentUsesDollarId(): void + { + $retriever = new UriRetriever(); + $schema = $retriever->retrieve('package://tests/fixtures/draft07-schema.json'); + + $this->assertObjectHasAttribute('$id', $schema); + $this->assertObjectNotHasAttribute('id', $schema); + $this->assertEquals('package://tests/fixtures/draft07-schema.json', $schema->{'$id'}); + } + + public function testRetrieveDraft07SchemaWithoutFragmentUsesDollarId(): void + { + $retriever = new UriRetriever(); + $schema = $retriever->retrieve('package://tests/fixtures/draft07-schema-without-fragment.json'); + + $this->assertObjectHasAttribute('$id', $schema); + $this->assertObjectNotHasAttribute('id', $schema); + $this->assertEquals('package://tests/fixtures/draft07-schema-without-fragment.json', $schema->{'$id'}); + } + + public function testRetrieveSchemaWithoutDialectDefaultsToDollarId(): void + { + $retriever = new UriRetriever(); + $schema = $retriever->retrieve('package://tests/fixtures/foobar.json'); + + $this->assertObjectHasAttribute('$id', $schema); + $this->assertObjectNotHasAttribute('id', $schema); + $this->assertEquals('package://tests/fixtures/foobar.json', $schema->{'$id'}); } public function testInvalidContentTypeEndpointsDefault(): void diff --git a/tests/fixtures/draft04-schema-with-fragment.json b/tests/fixtures/draft04-schema-with-fragment.json new file mode 100644 index 00000000..a80ee898 --- /dev/null +++ b/tests/fixtures/draft04-schema-with-fragment.json @@ -0,0 +1,9 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "properties": { + "foo": { + "type": "string" + } + } +} diff --git a/tests/fixtures/draft04-schema-without-fragment.json b/tests/fixtures/draft04-schema-without-fragment.json new file mode 100644 index 00000000..e67b850f --- /dev/null +++ b/tests/fixtures/draft04-schema-without-fragment.json @@ -0,0 +1,9 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema", + "type": "object", + "properties": { + "foo": { + "type": "string" + } + } +} diff --git a/tests/fixtures/draft07-schema-without-fragment.json b/tests/fixtures/draft07-schema-without-fragment.json new file mode 100644 index 00000000..52bf4972 --- /dev/null +++ b/tests/fixtures/draft07-schema-without-fragment.json @@ -0,0 +1,9 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "type": "object", + "properties": { + "foo": { + "type": "string" + } + } +} diff --git a/tests/fixtures/draft07-schema.json b/tests/fixtures/draft07-schema.json new file mode 100644 index 00000000..39f88b39 --- /dev/null +++ b/tests/fixtures/draft07-schema.json @@ -0,0 +1,9 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "properties": { + "foo": { + "type": "string" + } + } +}