Improve Resolver
@JanTvrdik, I think we must see this and the ideas in #6 and #11 as a whole and put a little more thought in it. AFAIK the issue isn't about correctness but usability. What's needed is a more convenient API to deal with paths/URIS in general (relative/absolute/not-specified). Implementation may then vary wildly.
I won't have much time in the next days unfortunalely, so here are just quick notes:
- A solution for #6 is a must-have IMO, but it's actually a little trickier than I thought, given we'll also want some kind of cache for resolved pointers.
- Opening
registerSchemacould have its uses, but allowing to register relative URIs might be a source of problems (how do we resolve relative URIs within the included schema, if any?) and in some cases, contrary to the spec (we'll just make blind substitutions instead of following the official resolution algorithm) - There are probably other things to explore, like adding shortcut methods on the validator for the most common cases (
validateFromUri($instance, $schemaUri),validateFromFile($instance, $schemaPath), etc.).
This should now hopefully solve #6 and #11. #15 is out of scope of this already large PR.
Thanks for your work. On the positive side:
- Conformance to RFC 6901 is a really good catch. The only missing part to make it complete now is the treatment of malformed pointers as errors.
- Changes to
Uriare most welcome. - Storing the root schema separately does solve #11.
On the other hand:
- #6 isn't solved yet
- There's something wrong in the refactoring of the resolver. The test you've deleted was failing for a good reason. You may have over-simplified the resolver behaviour.
#6 isn't solved yet
It should be. Functionally mentioned in https://github.com/stefk/JVal/issues/6#issuecomment-207998771 remained intentionally unimplemented because relative URLs cannot be handled reliably.
The test you've deleted was failing for a good reason.
I disagree. The specification regarding $ref and id is terrible, but the way I understand it, the evaluation process of the scoped-references.json schema should work as follows
- The whole schema has assigned URI
http://localhost:1234/valid/scoped.json - First
$refis resolved against current schema URI to
http://localhost:1234/valid/items-array.jsonand fetched from disk - Second
$refis resolved against current schema URI to
http://localhost:1234/valid/exclusiveMinimum-not-present.jsonand fetched from disk - New schema is declared with URI resolved to
http://localhost:1234/valid/exclusiveMaximum-not-present.json - Third
$refis resolved against current schema URI (which was changed!) to
http://localhost:1234/valid/exclusiveMaximum-not-present.jsonand fetched from memory
Note: the schema is actually sort-of invalid because content of http://localhost:1234/valid/scoped.json#/properties/baz should be identical to http://localhost:1234/valid/exclusiveMaximum-not-present.json but it not.
I don't see anything in the spec to support that reasonning. Scopes have nothing to do with "declaration" of schemas, they're just a way to alter the URI against which references will be resolved. They're also completely indifferent to the way references will be fetched (disk/memory/...). Reading the relevant section of the spec, I think the only possible interpretation is:
- The original resolution scope is the URI of the file (file://path/to/scoped-references.json).
- The first
idcreates the scope http://localhost:1234/valid/scoped.json. - References in
fooandbarare resolved against that scope, which gives:- http://localhost:1234/valid/item-array.json
- http://localhost:1234/valid/exclusiveMinimum-not-present.json
- The
idinbazalters the parent scope, making it http://localhost:1234/valid/exclusiveMaximum-not-present.json - The
$refinoneOfis resolved against that scope, leading to http://localhost:1234/valid/exclusiveMaximum-not-present.json#
The expected content of #/baz/oneOf/0is thus the whole schema located at that last URI, i.e.:
{
"maximum": 2
}
It is the case in the current implementation, and that's what the test is checking.