Skip to content

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

@penyaskito

Description

@penyaskito

Couldn't find an existing issue for this — closest is discussion #820 (general "supporting newer drafts"), please point me at a duplicate if I missed one.

Summary

UriRetriever::retrieve() unconditionally stamps every resolved schema with $jsonSchema->id = $resolvedUri;. The library's default dialect was bumped to Draft-6 in Factory::$defaultDialect and Draft-6 renamed id to $id, but UriRetriever was never updated to match. As a result, a Validator configured for Draft-6/7 still emits a Draft-4 id keyword on every URI-resolved schema.

Internally this is harmless — SchemaStorage::findSchemaIdInObject() already reads either id or $id (SchemaStorage.php:236-243). But anyone consuming the resolved schema externally — serializing it to JSON, sending it to a strict Draft-7 validator like Ajv, etc. — gets a schema with an unknown keyword:

Error: NOT SUPPORTED: keyword "id", use "$id" for schema ID

Minimal reproduction

use JsonSchema\Constraints\Factory;
use JsonSchema\DraftIdentifiers;
use JsonSchema\SchemaStorage;

$factory = new Factory();
$factory->setDefaultDialect(DraftIdentifiers::DRAFT_7);
/** @var SchemaStorage $storage */
$storage = $factory->getSchemaStorage();
$storage->addSchema('file:///tmp/example.json', (object) [
    '$defs' => (object) [
        'thing' => (object) ['type' => 'object'],
    ],
]);
$resolved = $storage->resolveRefSchema((object) ['$ref' => 'file:///tmp/example.json#/$defs/thing']);
var_dump(property_exists($resolved, 'id'));   // bool(true)  ← draft-04 keyword leaked
var_dump(property_exists($resolved, '$id'));  // bool(false)

Offending code

src/JsonSchema/Uri/UriRetriever.php (line 188-190):

if ($jsonSchema instanceof \stdClass) {
    $jsonSchema->id = $resolvedUri;
}

No dialect check.

Proposed fix

Make the annotation dialect-aware. Minimal, BC-preserving — Draft-3/4 callers keep getting id; Draft-6+ callers get $id.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions