Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clarify interaction of $ref and sibling properties #672

Closed
reitzig opened this issue Nov 12, 2018 · 3 comments
Closed

Clarify interaction of $ref and sibling properties #672

reitzig opened this issue Nov 12, 2018 · 3 comments

Comments

@reitzig
Copy link

reitzig commented Nov 12, 2018

I ran into an issue with inconsistent behaviour of different validators which I narrowed down to the following potential ambiguity in the spec (Draft 4).

In short, how do we interpret a schema fragment like this?

{
	"$ref": "#/definitions/foo",
	"enum": ["a"]
}

where

"definitions": {
	"foo": {
		"type": "string",
		"enum": ["a", "b", "c"]
	}
}

Does "b" validate against this schema (fragment)?

My intuition for the semantics of $ref is that sibling nodes would override the referenced schema; ruby-json-schema/json-schema seems to agree. However, neither jsonschemavalidator.net nor java-json-tools/json-schema-validator give the same result.

I couldn't find anything about this in the draft 4 specs. Only an official example suggested that the problem may be with the schema and the Ruby implementation.

I saw #523 and #515 but didn't read them completely; if I understand correctly, my understanding is incorrect and I should use

{
	"allOf": [
		{ "$ref": "#/definitions/foo" },
		{ "enum": ["a"] }
	]
}

This strikes me an unnecessary amount of boilerplate -- above version could easily be specified to mean exactly this -- but well. Is my understanding correct this far?

I assume that the discussion rests on this sentences in section 8.3 of draft 7, whose significance I completely missed during repeated readings:

All other properties in a "$ref" object MUST be ignored.

Even after reading it knowing what it must mean, I don't think it's as clear as it could be; the term "$ref object" is not specified. Proposal:

If property `$ref$ is present in an object schema, all other properties must be ignored.

In addition, I propose to make the specification more strict here: schemas that do not conform to this restriction should not be valid; loud errors are preferable over (presumably silent) ignoring.

MWE

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "title": "A test schema",
  "type": "object",
  "oneOf": [
    {
      "properties": {
        "type": {
          "$ref": "#/definitions/foo",
          "enum": ["a"]
        },
        "name": {
          "type": "string"
        }
      },
      "required": ["type", "name"]
    },
    {
      "properties": {
        "type": {
          "$ref": "#/definitions/foo",
          "enum": ["b"]
        },
        "id": {
          "type": "integer"
        }
      },
      "required": ["type", "id"]
    }
  ],
  "definitions": {
    "foo": {
      "type": "string",
      "enum": ["a", "b", "c"]
    }
  }
}

This schema validates with all abovementioned tools.

{ 
	"type": "a",
	"id": 77
}

This JSON does not validate with ruby-json-schema/json-schema (cf MWE) but validates on jsonschemavalidator.net.

@reitzig reitzig changed the title Clarify interaction of $ref and sibling nodes Clarify interaction of $ref and sibling properties Nov 12, 2018
@handrews
Copy link
Contributor

handrews commented Nov 12, 2018

Already addressed by #628, although it may not be entirely apparent through the diff, and other related work is scattered throughout recent PRs, e.g. the definition of "applicator keyword".

Basically, your example:

{
	"allOf": [
		{ "$ref": "#/definitions/foo" },
		{ "enum": ["a"] }
	]
}

can now be written as

{
    "$ref": "#/definitions/foo",
    "enum": ["a"]
}

and they behave identically. So there is no merging (any more than there was with allOf, so I suppose it depends on how you define "merge")- you just apply all of the keywords and their results are ANDed just like any other pair of keywords in the same schema object. But you don't need the extra wrappers to get this to work anymore, which also removes the ambiguity.

@reitzig
Copy link
Author

reitzig commented Nov 12, 2018

Cool, thanks!

So my original schema will be valid with draft 8 (or whatever it'll be called)?

@handrews
Copy link
Contributor

@reitzig yup! Hopefully the draft (whatever we call it, "draft-08" is the common shorthand but not technically correct by IETF rules so we need to figure that out) will be published by the end of the year. Implementations will take a bit to catch up but the last two drafts have gotten a good bit of attention so far.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants