for-GET/jesse

jesse does not fully respect internal references

Closed this issue · 1 comments

draft-wright-json-schema-00 (Internet-Draft October 13, 2016) | 8.2.1. Internal references states that:

Schemas can be identified by any URI that has been given to them, including a JSON Pointer or their URI given directly by "id".

In particular, the following schema will not work with jesse:

{
    "id": "http://example.net/root.json",
    "items": {
        "type": "array",
        "items": { "$ref": "#item" }
    },
    "definitions": {
        "single": {
            "id": "#item",
            "type": "integer"
        }
    }
}

Failing example with internal reference URI given directly by "id" (#item):

1> jesse:add_schema("http://example.net/root.json", <<"{\"id\":\"http://example.net/root.json\",\"items\":{\"type\":\"array\",\"items\":{\"$ref\":\"#item\"}},\"definitions\":{\"single\":{\"id\":\"#item\",\"type\":\"integer\"}}}">>, [{parser_fun, fun jsx:decode/1}]).
ok
2> jesse:validate("http://example.net/root.json", <<"[[1, 2, 3]]">>, [{parser_fun, fun jsx:decode/1}]).
{error,[{schema_invalid,[{<<"$ref">>,<<"#item">>}],
                        schema_invalid}]}

Successful example with internal reference given as JSON Pointer (#/definitions/single):

1> jesse:add_schema("http://example.net/root.json", <<"{\"id\":\"http://example.net/root.json\",\"items\":{\"type\":\"array\",\"items\":{\"$ref\":\"#/definitions/single\"}},\"definitions\":{\"single\":{\"id\":\"#item\",\"type\":\"integer\"}}}">>, [{parser_fun, fun jsx:decode/1}]).
ok
2> jesse:validate("http://example.net/root.json", <<"[[1, 2, 3]]">>, [{parser_fun, fun jsx:decode/1}]).
{ok,[[1,2,3]]}

Tools SHOULD take note of the URIs that schemas, including subschemas, provide for themselves using "id". This is known as "Internal referencing".

So it is recommended by IETF to support URIs both for schemas (which jesse currently does) and subschemas (which is lacking).

I have pushed a fix so that jesse works better with JSON paths e.g. this works now

{
    "id": "http://example.net/root.json",
    "items": {
        "type": "array",
        "items": { "$ref": "#/definitions/single" }
    },
    "definitions": {
        "single": {
            "id": "#item",
            "type": "integer"
        }
    }
}

As for internal references (id attribute), they are indeed not supported, nor do I have any intention to do so. A PR would obviously be considered, though in my experience the id attribute sugar does not only add very little value, but it also makes big schemata harder to follow (both by a human and programmatically composition-wise).