How do I describe mutually exclusive values of properties? - jsonschema

I have two properties (propOne and propTwo).
If one of the properties values is true the other must be set to false.
How do I describe this in jsonschema?
I can say if propOne is true require propTwo, but this isn't enough:
"anyOf": [
{
"not": {
"properties": {
"propOne": {
"const": true
}
},
"required": [
"propOne"
]
}
},
{
"required": [
"propTwo"
]
}
],
What is the most concise way to describe my requirements?
Edit:
Per the answer this does what I want. I know there is a handful of ways to describe this. It seems like oneOf is the most concise? I think if conditions would require more lines?
"oneOf": [
{
"type": "object",
"properties": {
"propOne": {
"const": true
},
"propTwo": {
"const": false
}
}
},
{
"type": "object",
"properties": {
"propOne": {
"const": true
},
"propTwo": {
"const": false
}
}
}
],

There are the if/then/else keywords, and also oneOf (see https://json-schema.org/understanding-json-schema/reference/conditionals.html)
So, in pseudocode:
must be an object.
require propOne and propTwo.
propOne is a boolean.
propTwo is a boolean.
and either of these are equivalent (when combined with the above restrictions):
if propOne is true, then propTwo is false, else propTrue is true.
oneOf:
propOne is true and propTwo is false.
propOne is false and propTwo is true.

Related

Should dependentSchemas property need to be added in additionalProperties

I am trying to write a schema, where if property A is present then property B or C should also per present using dependencyschema construct, and in my schema, I have turned off any additionalProperties.
{
"$schema": "https://json-schema.org/draft/2019-09/schema",
"$id": "PropertiesSchema.json",
"type": "object",
"properties": {
"A": { "type": "boolean" }
},
"additionalProperties": false,
"dependentSchemas": {
"A": {
"anyOf": [
{ "required": [ "B" ] },
{ "required": [ "C" ] }
],
"properties": {
"B": { "type": "boolean" },
"C": { "type": "boolean" }
}
}
}
}
but it is currently failing for below input becuase of additionalProperties construct
{ "A": true, "B": false } or { "A": true, "C": false }
So is it possible that dependentSchemas properties are allowed when additionalProperties is turned off?
Thus valid input should be
{ "A": true, "B": false } or { "A": true, "C": false }
but for any other property say D, it should fail-
{ "A": true, "D": false }
additionalProperties can only take into account properties (and patternProperties) at the same schema object level.
If you change this to unevaluatedProperties you will find it working.
unevaluatedProperties can "see through" applicator keywords, such as dependentSchemas. It must wait for other keywords to be resolved first, and is resolved last.

json-schema, array of object, unique key-value

I have the following schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"choices": {
"type": "array",
"items": {
"type": "object",
"properties": {
"value": {
"type": "string"
},
"isCorrect": {
"type": "boolean"
}
},
"required": ["value", "isCorrect"],
"additionalProperties": false
},
"minItems": 1,
"maxItems": 50,
"uniqueItems": true,
"additionalItems": false,
}
}
}
Which validates data
{
"choices": [
{
"value": "John",
"isCorrect": true
},
{
"value": "Doe",
"isCorrect": true
}
]
}
But I want isCorrect to have a single true (others false) in the array of the objects.
Is it possible to validate the uniqueness on a single key?
You can't check uniqueness based on a key, but you can use a combination of contains and maxContains to have the constraint you described.
In the properties.choices object, add the following...
"contains": {
"properties": {
"isCorrect": {
"const": true
}
}
},
"maxContains": 1,
You can check this using https://json-schema.hyperjump.io
The contains keyword makes sure that the array contains at least one item that is valid according to the subschema value.
The maxContains keyword, if the contains keyword is used, makes sure no more that number of items are valid according to the contains subschema value.
https://datatracker.ietf.org/doc/html/draft-bhutton-json-schema-validation-00#section-6.4.4

How to enforce only one property value to true in an array (JSON Schema)

I am trying to have JSON validation based on the following input:
{
"elements":[
{
"..."
"isSelected": true
},
{
"..."
"isSelected": false
},
{
"..."
"isSelected": false
}
]
}
The input is going to be valid if and only if we have "isSelected" set to "true" (and all the rest set to "false"). Can't have "isSelected: true" more than once (and all the rest need to be "false").
Tried with the following:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"definitions": {
"element":{
"type": "object",
"properties": {
"isSelected": {
"type": "boolean"
}
}
}
},
"properties": {
"elements": {
"type": "array",
"items": {
"$ref": "#/definitions/element"
},
"oneOf": [
{
"isSelected": true
}
]
}
},
}
unfortunately I don't think this is possible with json schema draft 7. the newest draft (2019-09) features the maxContains keyword, which would be able to validate this, but tooling for this draft is sparse so far. I don't know the tooling you're using, but if you are able to use 2019-09, the schema for 'elements' would look something like:
{
"type": "array",
"contains": {
"properties": {
"isSelected": {"const": true}
}
},
"maxContains": 1
}
oneOf isn't what you're looking for, for this - it checks that one of a set of schemas validates against the instance, not whether one of a set of instances validates against a schema.
This is not currently supported, but you may be interested in this proposal which intends to add a keyword to support key-based item uniqueness. It's not exactly the same, but I think it's related.

Preventing dependent property validation when the parent property does not exist

I am new to JSON schemas. I have a property (property1) that is dependent on another property (property2), which in turn is dependent on a third property (property3). I am trying to figure out how to prevent the schema from validating property1 if property2 doesn't exist. I am using the Python jsonschema module for validating.
I have a simple schema with three properties: species, otherDescription, and otherDescriptionDetail. The rules I'm trying to enforce are:
1) if species = "Human", otherDescription is required.
2) if species = "Human" and otherDescription != "None", otherDescriptionDetail is required.
3) if species != "Human", neither of the other two fields is required.
My test JSON correctly fails validation if species is "Human" and otherDescription doesn't exist, but it also reports that otherDescriptionDetail is a required property even though at this point it shouldn't be because there is no otherDescription value to compare it against. Is it possible to implement this logic with a JSON schema?
This is my schema:
"$schema": "http://json-schema.org/draft-07/schema#",
"$id":"http://example.com/test_schema.json",
"title": "annotations",
"description": "Validates file annotations",
"type": "object",
"properties": {
"species": {
"description": "Type of species",
"anyOf": [
{
"const": "Human",
"description": "Homo sapiens"
},
{
"const": "Neanderthal",
"description": "Cave man"
}
]
},
"otherDescription": {
"type": "string"
},
"otherDescriptionDetail": {
"type": "string"
}
},
"required": [
"species"
],
"allOf": [
{
"if": {
"properties": {
"species": {
"const": "Human"
}
}
},
"then": {
"required": ["otherDescription"]
}
},
{
"if": {
"allOf": [
{
"properties": {
"species": {
"const": "Human"
},
"otherDescription": {
"not": {"const": "None"}
}
}
}
]
},
"then": {
"required": ["otherDescriptionDetail"]
}
}
]
}
My test JSON is:
{
"species": "Human"
}
The output that I want:
0: 'otherDescription' is a required property
The output that I am getting:
0: 'otherDescription' is a required property
1: 'otherDescriptionDetail' is a required property
Any help would be greatly appreciated.
You need to defined otherDescription as a required property insilde allOf. Otherwise allOf block will pass even if otherDescription not available.
"if": {
"allOf": [
{
"properties": {
"species": {
"const": "Human"
},
"otherDescription": {
"not": {"const": "None"}
}
},
"required": ["otherDescription"]
}
]
},
"then": {
"required": ["otherDescriptionDetail"]
}

JSON Schema - anyOf within conditional?

I am trying to define a JSON schema with conditionals. I built an MVE which already doesn't work as I expect it.
The object I want to validate is:
{
"keiner": false,
"abdominal": true,
"zervikal": false
}
The conditional rule is simple. When "keiner" is true, both other values have to be false. If "keiner" is false, at least one of the other two has to be true.
I wrote this schema:
{
"type": "object",
"properties": {
"keiner": { "type": "boolean" },
"abdominal": { "type": "boolean" }
},
"if": {
"properties": {
"keiner": { "const": true }
}
},
"then": {
"properties" : {
"abdominal": { "const": false },
"zervikal": {"const": false }
}
},
"else": {
"properties": {
"anyOf": [
{ "abdominal": { "const": true } },
{ "zervikal": { "const" : true } }
]
}
}
}
But the Newtonsoft online validator gives the error message
Unexpected token encountered when reading value for 'anyOf'. Expected StartObject, Boolean, got StartArray.
for the line in which ´anyOf´ starts. This confuses me, as all examples I can find show anyOf followed by an array of options.
So what am I doing wrong? Why cannot I have a startArray after anyOf, and how do I write the schema correctly?
I guess this is the schema you are looking for: