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

Missing test for propertyNames behavior with anyOf for inheritance #255

Open
aaron-meyers opened this issue Mar 7, 2019 · 2 comments
Open
Labels
missing test A request to add a test to the suite that is currently not covered elsewhere.

Comments

@aaron-meyers
Copy link

aaron-meyers commented Mar 7, 2019

There is an example on the draft-06 release notes that demonstrates how to use propertyNames with anyOf to do inheritance that prevents additional properties (equivalent to additionalProperties: false behavior).

Quoted from: http://json-schema.org/draft-06/json-schema-release-notes.html

A workaround is available with the new "propertyNames" keyword:

 {
     "type": "object",
     "allOf": [
         {"$ref": "#/definitions/foo"},
         {"$ref": "#/definitions/bar"}
     ],
     "anyOf": [
         {"$ref": "#/definitions/fooNames"},
         {"$ref": "#/definitions/barNames"}
     ],
     "definitions": {
         "foo": {
             "properties": {
                 "foo": {"type": "string"}
             }
         },
         "fooNames": {
             "propertyNames": {"enum": ["foo"]}
         },
         "bar": {
             "properties": {
                 "bar": {"type": "number"}
             }
         },
         "barNames": {
             "propertyNames": {"enum": ["bar"]}
         }
     }
 }

This will allow an object with either “foo” or “bar” or both, but will fail validation if any other property is present. The "allOf" ensures that “foo” and “bar” will each be validated correctly if present, while the "anyOf" allows for properties with names in either allowed set, but forbids properties that are not listed in at least one set.

Based on this description, it would be expected that the following JSON is valid against the schema above

{
  "foo": "some string",
  "bar": 42
}

However, there are no tests for this behavior and the JSON.NET Schema implementation at least does not implement this behavior as described (the JSON above is considered invalid because it does not satisfy the anyOf constraint -- each propertyNames definition is evaluated independently and so both fail validation with the other property).

At this point we probably just have to wait for draft-08 to fix this since it may not make sense to expect JSON.NET Schema and other draft-06 implementations to implement this properly given that there wasn't a test case for it.

But there should be a test added for draft-08 (or the propertyNames feature reconsidered altogether if it doesn't actually work as described above).

@aaron-meyers
Copy link
Author

I've played around with this some more and I don't think the example from the release notes really makes any sense. To implement it would require very different semantics for validation of propertyNames inside an anyOf since it effectively requires each property name to be validated against the anyOf constraint rather than the object (with all its properties) as a whole.

I think this is correct pattern:

{
  "type": "object",
  "allOf": [
    { "$ref": "#/definitions/foo" },
    { "$ref": "#/definitions/bar" },
    {
      "propertyNames": {
        "anyOf": [
          { "$ref": "#/definitions/fooNames" },
          { "$ref": "#/definitions/barNames" }
        ]
      }
    }
  ],
  "definitions": {
    "foo": {
      "properties": {
        "foo": { "type": "string" }
      }
    },
    "fooNames": {
      "enum": [ "foo" ]
    },
    "bar": {
      "properties": {
        "bar": { "type": "number" }
      }
    },
    "barNames": {
      "enum": [ "bar" ]
    }
  }
}

@karenetheridge
Copy link
Member

Is this intended to test allOf or $ref specifically? If not, the schema would be a lot simpler if it was just presented as:

  "type": "object",
  "properties": {
    "foo": { "type": "string" },
    "bar": { "type": "number" }
  },
  "propertyNames": {
    "anyOf": [
      { "enum": [ "foo" ] },
      { "enum": [ "bar" ] }
    ]
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
missing test A request to add a test to the suite that is currently not covered elsewhere.
Projects
None yet
Development

No branches or pull requests

3 participants