Skip to content

fix: annotate resolved schemas with dialect-aware id keyword#912

Open
penyaskito wants to merge 3 commits into
jsonrainbow:mainfrom
penyaskito:fix/911-uri-retriever-dialect-aware-id
Open

fix: annotate resolved schemas with dialect-aware id keyword#912
penyaskito wants to merge 3 commits into
jsonrainbow:mainfrom
penyaskito:fix/911-uri-retriever-dialect-aware-id

Conversation

@penyaskito
Copy link
Copy Markdown
Contributor

Summary

  • UriRetriever::retrieve() now reads the root schema's $schema keyword to determine whether to annotate with id (Draft-3/4) or $id (Draft-6+)
  • Schemas without a $schema keyword default to $id, matching the library's Draft-6 default dialect
  • Updated testRetrieveSchemaFromPackage to assert structure instead of a brittle md5 hash

Context

UriRetriever::retrieve() unconditionally stamped $jsonSchema->id = $resolvedUri on every resolved schema. Draft-6 renamed id to $id, but the annotation was never updated. This leaks a Draft-4 keyword into schemas resolved under Draft-6/7, causing errors in strict validators (e.g. Ajv: NOT SUPPORTED: keyword "id", use "$id" for schema ID).

The dialect is detected from the root schema before pointer resolution, so sub-schemas inherit the correct keyword from their parent document.

Internally safe — SchemaStorage::findSchemaIdInObject() already reads both id and $id.

Test plan

  • Full test suite passes (6928 tests, 0 failures)
  • Verified Draft-04 meta-schema → id, Draft-07 → $id, no $schema$id

Fixes #911

UriRetriever::retrieve() unconditionally stamped resolved schemas with
the draft-04 "id" keyword. Draft-6 renamed this to "$id", but the
annotation was never updated.

Detect the dialect from the root schema's $schema keyword before pointer
resolution. Draft-3/4 schemas get "id"; Draft-6+ and schemas without an
explicit $schema keyword get "$id" (matching the library's default).

Internally safe because SchemaStorage::findSchemaIdInObject() already
reads both keywords. Fixes the issue for external consumers of resolved
schemas (e.g. strict Draft-7 validators like Ajv that reject the
unknown "id" keyword).

Fixes jsonrainbow#911

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Comment on lines -342 to +343
$this->assertEquals('454f423bd7edddf0bc77af4130ed9161', md5(json_encode($schema)));
$this->assertEquals('object', $schema->type);
$this->assertObjectHasAttribute('$id', $schema);
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

⚠️ I'm not sure why an md5 was used here. Maybe it should just update this to the new md5 now that it uses $id instead of id?

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes UriRetriever::retrieve() unconditionally stamping the Draft-4 id keyword onto every URI-resolved schema. It now inspects the loaded root schema's $schema keyword and uses id only for Draft-3/4, defaulting to $id otherwise (matching the library's Draft-6 default dialect). The corresponding test no longer relies on a brittle md5 of the serialized schema.

Changes:

  • Import DraftIdentifiers in UriRetriever and detect the dialect from the root schema before pointer resolution.
  • Stamp the resolved URI onto either id (Draft-3/4) or $id (everything else) in UriRetriever::retrieve().
  • Replace the md5-of-JSON assertion in testRetrieveSchemaFromPackage with structural assertions on type and the presence of $id.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
src/JsonSchema/Uri/UriRetriever.php Detect dialect from root schema's $schema and annotate with id for Draft-3/4, $id otherwise.
tests/Uri/UriRetrieverTest.php Switch the package-retrieval test from a brittle md5 hash to structural assertions reflecting the new $id annotation.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/JsonSchema/Uri/UriRetriever.php Outdated
penyaskito and others added 2 commits May 27, 2026 22:06
…word

The dialect comparison now strips the trailing # from the $schema value
and compares against withoutFragment() constants, so schemas declaring
e.g. "http://json-schema.org/draft-04/schema" (without #) correctly
get `id` instead of falling through to `$id`.

Adds 5 tests covering Draft-04 and Draft-07 with/without fragment, plus
the no-$schema default.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

UriRetriever annotates resolved $refs with draft-04 "id" even when configured for Draft-6+

3 participants