Reputation: 501
Here is the JSON Schema and the JSON as provided below in the link for illustartion purpose.
Format: The Individual JSON object (with their additional attributes and may vary with other object in the array) within array can be of any 3 region: 'america', 'asia' and 'europe' and at-least on the type of region object should be there. This can be achieved by array minItems property)
Problem Statement:
The Individual JSON object within array can be of any 3 region: 'america', 'asia' and 'europe' and at-least on the type of region object should be there
==> I am able to solve this by putting all the region objects in the anyOf array as I want to match at-least one of the valid region object.
Either the JSON object 'asia' or 'europe' can exist along with other region type. Both cannot coexist.
==> I tried to use 'oneOf' but its passing the ajv validation. Actually it should fail. Can anyone help. Thanks
JSON Schema
{
"type": "object",
"properties": {
"stat_data": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"properties": {},
"anyOf": [{
"required": ["region"],
"properties": {
"region": {
"enum": ["america"]
},
"country": {
"type": "string"
},
"population": {
"type": "string"
}
}
},
{
"oneOf": [
{
"required": ["region"],
"properties": {
"region": {
"enum": ["asia"]
},
"country": {
"type": "string"
},
"details": {
"type": "object",
"properties": {
"language": {
"type": "string"
},
"tz": {
"type": "string"
}
}
}
}
}, {
"required": ["region"],
"properties": {
"region": {
"enum": ["europe"]
},
"country": {
"type": "string"
},
"language": {
"type": "string"
}
}
}
]
}
]
}
}
}
}
JSON Object to FAIL as both "asia" and "europe" type object cannot co-exist.
{
"stat_data": [{
"region": "america",
"country": "USA",
"states": "50"
}, {
"region": "asia",
"country": "Japan",
"details": {
"language": "Japanese",
"tz": "utc+9.00"
}
}, {
"region": "europe",
"country": "finland",
"language": "Finnish"
}
]
}
JSON Object to PASS as ONLY "asia" type object exist.
{
"stat_data": [{
"region": "america",
"country": "USA",
"states": "50"
}, {
"region": "asia",
"country": "Japan",
"details": {
"language": "Japanese",
"tz": "utc+9.00"
}
}
]
}
JSON Object to PASS as ONLY "europe" type object exist.
{
"stat_data": [{
"region": "america",
"country": "USA",
"states": "50"
}, {
"region": "europe",
"country": "finland",
"language": "Finnish"
}
]
}
Upvotes: 4
Views: 4703
Reputation: 12355
I can see why you tried the approach you did, however it does not work as expected because you've defined that, each item in the array may be america
or (europe
or asia
), which isn't what you want.
Remember, items
applies the value schema to EACH element in the array. It expresses no constraints on the overall array itself. contains
checks that at least one of the items in the array validates against its value schema.
What you want is to say, each item in the array may have america
or europe
or asia
, but the array may not contain europe
if it contains asia
, and the inverse.
I've refactored the schema and made some changes.
Hopefully you can also see the intent is clear in the use of oneOf
>> (contains
and not
> contains
).
JSON Schema works by adding constraints. You generally cannot define constraint by omission.
JSON Schema and data validation demo
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"containtsAsia": {
"contains": {
"properties": {
"region": {
"const": "asia"
}
}
}
},
"containsEurope": {
"contains": {
"properties": {
"region": {
"const": "europe"
}
}
}
}
},
"type": "object",
"properties": {
"stat_data": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"properties": {
"region": {
"enum": [
"america",
"asia",
"europe"
]
},
"country": {
"type": "string"
},
"population": {
"type": "string"
}
}
},
"oneOf": [
{
"allOf": [
{
"$ref": "#/definitions/containtsAsia"
},
{
"not": {
"$ref": "#/definitions/containsEurope"
}
}
]
},
{
"allOf": [
{
"$ref": "#/definitions/containsEurope"
},
{
"not": {
"$ref": "#/definitions/containtsAsia"
}
}
]
}
]
}
}
}
Upvotes: 5