jhthorsen / json-validator

:cop: Validate data against a JSON schema
https://metacpan.org/release/JSON-Validator
56 stars 57 forks source link

$refs not correctly resolved (unsupported features) #186

Closed karenetheridge closed 3 years ago

karenetheridge commented 4 years ago

$ref resolution support is incomplete.

This feature is described at https://json-schema.org/understanding-json-schema/structuring.html#using-id-with-ref. It would require updates to the bits of the code that construct JSON::Validator::Ref objects, to find the document section with the referenced $id (as opposed to a json pointer).

This change will also probably require fixing an existing bug, where invalid json pointers are supported. See the test schema t/spec/test-definitions-key.json, which uses { "$ref": "../definitions/age.json#type" } -- "type" is not a valid json pointer as it does not start with /. Since there is no document fragment labelled with "$id":"type", this reference should fail to resolve.

When a relative filename reference is seen, the document level $id should be used to resolve it, rather than immediately assuming it is a relative path on the local disk. (e.g. "$id":"http://foo.com/schema.json" and then later "$ref":"bar.json/baz" should resolve not to the local file "$CWD/bar.json", but rather "http://foo.com/bar.json".

Both of these scenarios are described in the draft-07 spec at https://tools.ietf.org/html/draft-handrews-json-schema-01#section-8.3.2

karenetheridge commented 4 years ago

Another (arguable) bug (or, more charitably, "loose syntax interpretation") that probably would need to be fixed/tightened up is the use of same-document references. Currently, "$ref" : "/foo/bar" is acceptable as a json pointer /foo/bar in the same schema. However, my reading of https://tools.ietf.org/html/draft-handrews-json-schema-01#section-8.3.2 and https://tools.ietf.org/html/rfc3986#section-3.5 is that references that are only fragments must start with # -- therefore "$ref" : "/foo/bar" should fail to resolve unless there is a "$id" : "/foo/bar" somewhere in the document, or an absolute file /foo/bar that exists on disk. (We could be helpful and fail with a warning "perhaps you meant #/foo/bar?")

karenetheridge commented 4 years ago

More: https://tools.ietf.org/html/draft-handrews-json-schema-01#section-5:

plain name fragment identifiers .. are reserved for referencing locally named schemas. All fragment identifiers that do not match the JSON Pointer syntax MUST be interpreted as plain name fragment identifiers.

Therefore -- $refs that reference a section in the same document with an $id label (as opposed to using a json pointer) must start with # as well. (https://tools.ietf.org/html/draft-handrews-json-schema-01#section-8.2.3)

jhthorsen commented 4 years ago

Some of the issues above cannot be cleaned up, because they were added to be able to read OpenAPI specs. I don't remember exactly which rules apply to what, but it will probably be clear if you try to fix it and run https://github.com/mojolicious/json-validator/blob/master/run-all-tests.sh.

I think this issue is another reason to push forward the suggested changes in #185.

jhthorsen commented 3 years ago

If I have understood it correctly, then this has been resolved in 93dfde2.