Conditional validation in JSON schema on nested field - json

I tried searching, but I'm not quite sure how to put this in words! The point of confusion is how "required" works in JSON schema v4.
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"prop1": {
"type": "array",
"items": {
"type": "object",
"properties": {
"A": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
enum:["abc","bcd"]
}
},
"required": [
"name"
]
}
}
},
"required": [
"A"
]
}
},
"prop2": {
"type": "array",
"items": {
"type": "object",
"properties": {
"field": {
"type": "string"
}
},
"required": [
"field"
]
}
}
},
"required": [
"prop1"
]
}
Here I want to set a rule that if prop1.name=="abc" then only prop2 is required otherwise prop2 is optional, how to do that ?

Related

Json schema permits override of fields in objects in array

I have an json that looks like this
"List": {
{"Color": "red"},
{}
},
"Color": "grey"
}
whereas it means that the default color is grey, and the object in the list could override this Color.
The schema should allow the json to pass as long as default color(the property in the same level of List) is present. If not, it shall only allow the json to pass the schema check if all items in the list have specified a "Color".
May I know how can I write a json schema that does this check? I am aware of anyOf but I don't think it can check for all items in the array.
I tried
{
"type": "object",
"properties": {
"List": {"type": "array", "items": {"$ref:" "#/definitions/Item"}},
"Color": {"type": "string"}
},
"definitions": {
"Item": {"type: "object", "properties": " {"Color": {"type": "string"}}}
},
"anyOf": {
{
"type": "object",
"required": ["Color"]
},
{
"type": "object",
"List": {
"type": "array",
"items": {"$ref": "#/definitions/Item", "required": ["Color"]}
}
}
}
But it does not seem that the required color for the anyOf[1] is picked up by the validator.
Please help.! Thank you.
The schema in the other answer is correct, but is unnecessarily complicated. Here's an example that removes duplication and make the schema easier to read.
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"List": {
"type": "array",
"items": {
"type": "object",
"properties": {
"Color": { "type": "string" },
"Shape": { "type": "string" }
}
}
},
"Color": { "type": "string" },
"Shape": { "type": "string" }
},
"required": ["List"],
"allOf": [
{ "$ref": "#/definitions/color-required-if-no-default-color" },
{ "$ref": "#/definitions/shape-required-if-no-default-shape" }
],
"definitions": {
"color-required-if-no-default-color": {
"anyOf": [
{ "required": ["Color"] },
{
"properties": {
"List": {
"items": { "required": ["Color"] }
}
}
}
]
},
"shape-required-if-no-default-shape": {
"anyOf": [
{ "required": ["Shape"] },
{
"properties": {
"List": {
"items": { "required": ["Shape"] }
}
}
}
]
}
}
}
I think I found out a way:
Schema is like below
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {"Color": {"type":"string"}, "Shape": {"type": "string"}},
"allOf":[
{
"anyOf": [
{
"required": ["Color"],
"properties": {"List": {"type": "array", "items": {"$ref": "#/definitions/Item"}}}
},
{
"properties": {"List": {"type": "array", "items": {"$ref": "#/definitions/ColorItem"}}}
}
]
},
{
"anyOf": [
{
"required": ["Shape"],
"properties": {"List": {"type": "array", "items": {"$ref": "#/definitions/Item"}}}
},
{
"properties": {"List": {"type": "array", "items": {"$ref": "#/definitions/ShapeItem"}}}
}
]
}
],
"required": ["List"],
"definitions": {
"Item": {
"type": "object",
"properties": {}
},
"ColorItem": {
"allOf": [{"$ref": "#/definitions/Item"},
{"properties": {"Color": {"type": "string"}}, "required": ["Color"]}]
},
"ShapeItem": {
"allOf": [{"$ref": "#/definitions/Item"},
{"properties": {"Shape": {"type": "string"}}, "required": ["Shape"]}]
}
}
}
Basically this does what I want. So it will pass the json only if either there is a Color/Shape read from top-level json, or we can find it in the array.

JSON Schema for strict objects in an array

I have created a JSON schema to validate a simple JSON file. The good news is that it validates in the way that I intended, in that any number of booking elements can appear in any order, and no extra properties are allowed in each type of booking element.
Ideally I would like to remove the full list of possible properties in a bookingElement object (id, type, depair, destair, city) in the JSON schema, and just leave the oneOf lists, which show clearly which fields are allowed in each different type of element.
Can anyone provide a version of the schema without that full list that still applies the strict rules?
This is the JSON:
{
"bookingElements": [
{
"id" : "00003",
"type" : "flight",
"depair" : "LHR",
"destair" : "CDG"
},
{
"id" : "00008",
"type" : "hotel",
"city" : "Paris"
}
]
}
The schema is:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"additionalProperties": false,
"properties": {
"bookingElements": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"properties": {
"id": {
"type": "string"
},
"type": {
"type": "string"
},
"depair": {
"type": "string"
},
"destair": {
"type": "string"
},
"city": {
"type": "string"
}
},
"oneOf": [
{
"type": "object",
"additionalProperties": false,
"properties": {
"id": {
"type": "string"
},
"type": {
"type": "string"
},
"depair": {
"type": "string"
},
"destair": {
"type": "string"
}
}
},
{
"type": "object",
"additionalProperties": false,
"properties": {
"id": {
"type": "string"
},
"type": {
"type": "string"
},
"city": {
"type": "string"
}
}
}
]
}
}
},
"required": [
"bookingElements"
]
}
Ideally the JSON schema would look something closer to the following:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"additionalProperties": false,
"properties": {
"bookingElements": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"oneOf": [
{
"type": "object",
"additionalProperties": false,
"properties": {
"id": {
"type": "string"
},
"type": {
"type": "string"
},
"depair": {
"type": "string"
},
"destair": {
"type": "string"
}
}
},
{
"type": "object",
"additionalProperties": false,
"properties": {
"id": {
"type": "string"
},
"type": {
"type": "string"
},
"city": {
"type": "string"
}
}
}
]
}
}
},
"required": [
"bookingElements"
]
}

AJV schema validation error

I have the input json like below,
{"contents":[{"type":"field"},{"type":"field","itemId":"594b9980e52b5b0768afc4e8"}]}
the condition is,
if the type is 'field', then 'itemId' should be the required field
and if the type is 'fieldGroup' or 'subSection', then 'itemId' is optional
This is the Json Schema I tried and its not working as expected,
"type": "object",
"additionalProperties": false,
"properties" : {
"contents" : {
"type" : "array",
"items": {"$ref": "#displayItem" }
}
},
"definitions": {
"displayItem" : {
"id": "#displayItem",
"type": "object",
"items": {
"anyOf": [
{"$ref": "#fieldType"},
{"$ref": "#fieldGroupSubSectionType"}
]
}
},
"fieldType" : {
"id": "#fieldType",
"type": "object",
"additionalProperties": false,
"properties": {
"itemId": {
"type": "string"
},
"type": {
"type": "string",
"enum": ["field"]
}
}
},
"fieldGroupSubSectionType" : {
"id": "#fieldGroupSubSectionType",
"type": "object",
"additionalProperties": false,
"properties": {
"itemId": {
"type": [ "string", "null" ]
},
"type": {
"type": "string",
"enum": [
"fieldGroup",
"subSection"
]
}
}
}
}
Any help / workaround with Sample Json Schema to achieve the above use case is appreciated.
If I understand the description of what you want correctly, then the json example you provide is not valid since it has a type: "field" but does not have an "itemId" property.
Assuming that is true. Instead of using
type: ["string", null]
use the required property.
I changed your schema a bit, instead of having separate definitions I inlined them, but other than that (and the use of required) is the same:
{
"type": "object",
"additionalProperties": false,
"properties": {
"contents": {
"type": "array",
"items": {
"anyOf": [
{
"type": "object",
"additionalProperties": false,
"properties": {
"itemId": {
"type": "string"
},
"type": {
"type": "string",
"enum": [
"field"
]
}
},
"required": [
"itemId"
]
},
{
"type": "object",
"additionalProperties": false,
"properties": {
"itemId": {
"type": "string"
},
"type": {
"type": "string",
"enum": [
"fieldGroup",
"subSection"
]
}
}
}
]
}
}
}
}
Here is your answer with a little cleanup for best practices and style. The trick is that you need to use implication "a implies b <=> (not a) or b". In this case you have "type = field implies itemId is required <=> type is not field or itemId is required".
{
"type": "object",
"properties": {
"contents": {
"type": "array",
"items": { "$ref": "#/definitions/displayItem" }
}
},
"definitions": {
"displayItem": {
"type": "object",
"properties": {
"itemId": { "type": "string" },
"type": { "enum": ["field", "fieldGroup", "subSection"] }
},
"anyOf": [
{ "not": { "$ref": "#/definitions/fieldType" } },
{ "required": ["itemId"] }
]
},
"fieldType": {
"properties": {
"type": { "enum": ["field"] }
}
}
}
}

JSON schema validdation - oneOf with array of mixed object type

I am trying to build up a JSON schema, where the JSON data has an array of mixed object types. I am trying to use oneOf, however, it seems that I am missing something, as my JSON data fails to validate against the schema.
Below are what I have done so far.
Schema:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"definitions": {
"Entity": {
"type": "object",
"additionalProperties": false,
"properties": {
"Property": {
"type": "string"
},
"Value": {
"type": "string"
}
},
"required": [ "Property", "Value" ]
},
"NavEntity": {
"type": "object",
"additionalProperties": false,
"properties": {
"Property": {
"type": "string"
},
"NavigationalEntities": {
"type": "array",
"items": {
"$ref": "#/definitions/Entity"
}
}
},
"required": [ "Property", "NavigationalEntities" ]
}
},
"additionalProperties": true,
"name": "/",
"properties": {
"Entities": {
"type": "array",
"minLength": 1,
"uniqueItems": true,
"items": {
"oneOf": [
{ "$ref": "#/definitions/Entity" },
{ "$ref": "#/definitions/NavEntity" }
],
"additionalProperties": false
}
}
}
}
And here is my JSON data:
{
"Entities": [
{
"Property": "ABC",
"NavigationalEntities": [
{
"Property": "ABC1",
"Value": "123"
}
]
},
{
"Property": "ABCD",
"Value": "ABCD"
}
]
}
When I try to validate this, I get error: "Additional properties not allowed". This can also be seen here.
Please let me know what I am missing here.
The problem is the "additionalProperties": false included in the items keyword within the Entities property.
You are specifying both:
all items should not have any additional properties that those
defined in items object (and you did not define any).
all items must verify one of Entity or NavEntity.
If you remove the last "additionalProperties": false, everything is ok. And you don't need it because both Entity and NavEntity have it included.
Proposed schema:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"definitions": {
"Entity": {
"type": "object",
"additionalProperties": false,
"properties": {
"Property": {
"type": "string"
},
"Value": {
"type": "string"
}
},
"required": [ "Property", "Value" ]
},
"NavEntity": {
"type": "object",
"additionalProperties": false,
"properties": {
"Property": {
"type": "string"
},
"NavigationalEntities": {
"type": "array",
"items": {
"$ref": "#/definitions/Entity"
}
}
},
"required": [ "Property", "NavigationalEntities" ]
}
},
"additionalProperties": true,
"name": "/",
"properties": {
"Entities": {
"type": "array",
"minLength": 1,
"uniqueItems": true,
"items": {
"oneOf": [
{ "$ref": "#/definitions/Entity" },
{ "$ref": "#/definitions/NavEntity" }
]
}
}
}
}

properties inside a oneOf operator is not being validated as I want

I have problems validating/understanding the "oneOf" operator.
JSON SCHEMA:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"QuerySpecification": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"properties": {
"FieldName": {
"type": "string"
}
},
"required": [
"FieldName"
],
"oneOf": [
{
"properties": {
"SimpleQuery": {
"type": "string"
}
}
},
{
"properties": {
"CompositeQuery": {
"type": "string"
}
},
"additionalProperties": false
}
]
}
}
}, "required": ["QuerySpecification"]
}
I would expect either "SimpleQuery" or "CompositeQuery" would be required in the JSON input, but it is validating OK without specifying neither of them.
JSON INPUT:
{
"QuerySpecification": [{
"FieldName": "Andreas"
}]
}
Figured out the answer
JSON SCHEMA:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"QuerySpecification": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"properties": {
"FieldName": {
"type": "string"
},
"SimpleQuery": {
"type": "string"
},
"CompositeQuery": {
"type": "string"
}
},
"oneOf": [{
"required": ["SimpleQuery"]
},{
"required": ["CompositeQuery"]
}],
"required": [
"FieldName"
],
"additionalProperties": false
}
}
}, "required": ["QuerySpecification"]
}
This schema will not validate with
{
"QuerySpecification": [{
"FieldName": "Andreas"
}]
}
..But this
{
"QuerySpecification": [{
"FieldName": "Andreas",
"SimpleQuery": "hei"
}]
}
Will validate