4

I want to perform JSON validation on my schema, which has four properties:

  • group
  • partition
  • select
  • features

If using either group or partition, then features is required. If using select, then features is prohibited. (Note that this seems to be a different case than in this question - I don't want to make features 'not required', but make it so if you include it, it's a validation error.

So my three options are:

  • group AND features
  • partition AND features
  • select AND NOT features

I've encoded these as:

"oneOf": [
  { "required": [ "group", "features" ] },
  { "required": [ "partition", "features" ] },
  { "required": [ "select" ] }
]

But I can't figure out how to appropriately force features to be excluded from the last option - or is this even a possibility?

user655321
  • 1,572
  • 2
  • 16
  • 33
  • you can define several schemas any of that valid, and place additionalProperties to false – VelikiiNehochuha Mar 07 '19 at 22:20
  • Does this answer your question? [JSON schema - valid if object does \*not\* contain a particular property](https://stackoverflow.com/questions/30515253/json-schema-valid-if-object-does-not-contain-a-particular-property) – Steve Chambers Dec 22 '22 at 14:41

3 Answers3

4

There are several ways to model this. If you want to have the freedom to allow additional properties, while only explicitly excluding a property called "features", you can use the not keyword:

"oneOf": [
  { "required": [ "group", "features" ] },
  { "required": [ "partition", "features" ] },
  { "required": [ "select" ], "not": { "required": ["features"] } }
]

The not keyword evaluates as "valid" if the sub-schema is not valid, and evaluates to "invalid" if the sub-schema is valid.

Erwin Bolwidt
  • 30,799
  • 15
  • 56
  • 79
  • 1
    At least within Visual Studio, using `not` in this way still lets me use both `select` and `features` together. I do want to be able to include other properties, but explicitly not `features`. – user655321 Mar 07 '19 at 23:45
  • 1
    I am no expert, but using "not" with "required" like this does not prevent documents from containing "features" - it simply is not required that documents contain "features". – Jonathan Hartley Jun 07 '19 at 15:12
  • 1
    You misunderstand the spec. The not rule succeeds when the sub rule fails and vice versa. The required rule succeeds if the property exists and fails if it doesn't; not with required succeeds if the property is missing and fails if it exists. – Erwin Bolwidt Jun 07 '19 at 23:49
1

You can define several schemas any of that valid

   {
        "anyOf": [
            { "$ref": "#/definitions/group" },
            { "$ref": "#/definitions/partition" },
            { "$ref": "#/definitions/select" },
        ]
    }

and for select you can define schema with additionalProperties set to false, like so

{
  "type": "object",
  "properties": {
    "select": {"type": "string"}
  },
  "additionalProperties": false
}

Then you get error like this:

ValidationError: Additional properties are not allowed

VelikiiNehochuha
  • 3,775
  • 2
  • 15
  • 32
  • I am no expert, but the end of this section https://json-schema.org/understanding-json-schema/reference/combining.html#allof says that "additionalProperties" requires that "properties" is defined at the top level within the object, and does not work when "properties" is deep within an "anyOf". Am I misunderstanding? – Jonathan Hartley Jun 07 '19 at 15:17
  • By "item", did you mean "items" ? The OP doesn't talk about an array, so why is that there? Apologies if I'm just misunderstanding. – Jonathan Hartley Jun 07 '19 at 15:21
  • 1
    By item, I mean any named object, that we describe into schema, you can safely remove item wrapper if you describe single object. – VelikiiNehochuha Jun 07 '19 at 16:04
  • Thanks! Also, I tried your solution out, and it's working for me, so clearly my first comment is misguided. Thanks for the answer! :-) – Jonathan Hartley Jun 07 '19 at 16:27
1

There is a trick proposed in a non-accepted answer to this related question, which involves the usage of "not": {}. That is, in case a property is present, can not satisfy any schema. Thus, it can not be present.

{
    "$schema": "http://json-schema.org/draft-07/schema#",
    "oneOf": [
        {
            "properties": {
                "group": {
                    "type": "string"
                },
                "features": {
                    "type": "string"
                }
            },
            "required": [
                "group",
                "features"
            ]
        },
        {
            "properties": {
                "partition": {
                    "type": "string"
                },
                "features": {
                    "type": "string"
                }
            },
            "required": [
                "partition",
                "features"
            ]
        },
        {
            "properties": {
                "select": {
                    "type": "string"
                },
                "features": {
                    "not": {}
                }
            },
            "required": [
                "select"
            ]
        }
    ]
}
jruizaranguren
  • 12,679
  • 7
  • 55
  • 73