why doesn't json schema validate definitions defined in required attribute - json

I'm trying to create a json schema that validates an object depending on its type. It picks the right definition, however, it doesn't validate the required attributes in the selected definition. Here is the json schema i am trying:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"literal": {
"type": "object",
"properties": {
"raw": { "type": "string" }
},
"required": ["raw"],
"additionalProperties": false
},
"identifier": {
"type": "object",
"properties": {
"name": { "type": "string" }
},
"required": ["name"],
"additionalProperties": false
}
},
"type": "object",
"oneOf": [
{
"type": "object",
"properties": {
"type": {
"enum": ["Literal"]
},
"content": { "$ref": "#/definitions/literal" }
}
},
{
"type": "object",
"properties": {
"type": {
"enum": ["Identifier"]
},
"content": { "$ref": "#/definitions/identifier" }
}
}
],
"required": ["type"]
};
the following schema is valid, even tho its missing the "raw" property:
{ "type" : "Literal" }
thanks

There is no keyword content in JSON Schema spec.
Once you have asserted "type":"object" in root schema, there is no need to do it again in subschema.
In order to combine object type enumerated value with associated extended definition, you need allOf keyword.
Also in definitions if you use "additionalProperties": false you have to list all properties of the object (see "type": {}). For previously defined/validated properties you can just use permissive schema: {} or true.
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"literal": {
"properties": {
"type": {},
"raw": { "type": "string" }
},
"required": ["raw"],
"additionalProperties": false
},
"identifier": {
"properties": {
"type": {},
"name": { "type": "string" }
},
"required": ["name"],
"additionalProperties": false
}
},
"type": "object",
"oneOf": [
{
"allOf": [
{
"properties": {
"type": {
"enum": ["Literal"]
}
}
},
{"$ref": "#/definitions/literal"}
]
},
{
"allOf": [
{
"properties": {
"type": {
"enum": ["Identifier"]
}
}
},
{"$ref": "#/definitions/identifier" }
]
}
],
"required": ["type"]
}

Related

If-then condition in JSON Schema isn't working

Following is the jsonSchema.
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "array",
"items": [
{
"type": "object",
"properties": {
"isMerchant": {
"type": "boolean"
},
"isAgent": {
"type": "boolean"
},
"cashLoan": {
"type": "boolean"
},
"personalDetail": {
"type": "string"
},
"contact": {
"type": "object",
"properties": {
"email": {
"type": "string"
},
"mobile": {
"type": "integer"
},
"area": {
"type": "string"
},
"state": {
"type": "string"
}
},
"required": ["state"]}
},
"required": ["isMerchant","cashLoan","contact"],
"allOf": [
{
"if": {
"properties": {
"isMerchant": {"enum": [true]}
}
},
"then": {
"required": [ "isAgent","email","mobile"]
}
},
{
"if": {
"properties": {
"cashLoan": {"enum": [true]}
}
},
"then": {
"required": ["personalDetail"]
}
}
]
}
]
}
Expectation is to validate the corresponding JSON data with this JSON schema. where conditions are as follows -
If 'isMerchant' = true then the params 'isAgent', 'email', 'mobile' should be present in the json file.
If 'cashLoan' = true then param 'personalDetail' should be present.
With draft 2020-12, the type of the items keyword can only be object or boolean.
You need to add a "requires": [...] to your if conditions, because the properties keyword will evaluate to true if the property is not present at all, therefore you are entering the then conditionals when you don't intend to.

AJV required property not respected

Trying to validate a JSON using AJV schema validator, but without success to make required parameter to work.
Json to validate:
{
"rootObject": {
"levelOneObject": {
"menu": {
}
}
}
}
Validation schema:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$ref": "#/definitions/Root",
"definitions": {
"Root": {
"type": "object",
"additionalProperties": true,
"properties": {
"rootObject": {
"$ref": "#/definitions/RootObject"
}
},
"required": ["rootObject"]
},
"RootObject": {
"type": "object",
"additionalProperties": true,
"properties": {
"levelOneObject": {
"$ref": "#/definitions/LevelOneObject"
}
},
"required": [
"levelOneObject"
],
"title": "root"
},
"LevelOneObject": {
"type": "object",
"additionalProperties": true,
"properties": {
"menu": {
"type": "object",
"items": {
"$ref": "#/definitions/Menu"
}
}
},
"required": ["menu"],
"title": "LevelOneObject"
},
"Menu": {
"type": "object",
"additionalProperties": true,
"properties": {
"overflow": {
"type": "object",
"properties": {
"maxItems": {
"type": "number"
}
}
}
},
"required": ["overflow"]
}
}
}
When I run the validator the schema is valid, although the menu object does not contain overflow property, even though is set as required in validation schema.
Why is required not taken in consideration?

Conditional check in JSON schema

I have following JSON schema:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"additionalProperties": false,
"properties": {
"Payload": {
"type": "object",
"additionalProperties": false,
"properties": {
"Person": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"properties": {
"Id": {
"type": "string"
},
"Name": {
"type": "string"
}
},
"required": [
"Id",
"Name"
]
}
}
}
},
"Reference": {
"type": "object",
"additionalProperties": false,
"properties": {
"Status": {
"anyOf": [
{
"Passed": {
"type": "string"
},
"Failed": {
"type": "string"
}
}
]
}
}
}
},
"anyOf": [
{
"additionalProperties": false,
"properties": {
"Status": {
"type": "string",
"enum": [
"Failed"
]
}
},
"required": [
"Reference"
],
"not": {
"required": [
"Payload"
]
}
},
{
"additionalProperties": true,
"properties": {
"Status": {
"type": "string",
"enum": [
"Passed"
]
}
},
"required": [
"Reference"
]
}
]
}
I want to check if JSON message has status failed then person array should not be present.
It should be present only if status is passed.
I tried following solution here but definitely i am doing something wrong as validator passes with Failed status and person details present. Can someone tell what I may be doing wrong?
You have a few issues.
/properties/Reference/properties/Status
This isn't a valid schema. It looks like you're trying to describe an enum.
additionalProperties
The reason is complicated, but the conditional patterns don't work with additionalProperties. The good news is it's also unnecessary. You can just leave those out.
/anyOf
Looks like you're using the "Enum" pattern, but the implication pattern is better in this case because only one of the enum states has additional constraints.
Conditional on nested property
Your schemas that define the Reference.Status value are actually just pointing to Status. You need a schema that describes the parent property as well.
The following does what I think your schema was trying to do.
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"additionalProperties": false,
"properties": {
"Payload": {
"type": "object",
"additionalProperties": false,
"properties": {
"Person": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"properties": {
"Id": { "type": "string" },
"Name": { "type": "string" }
},
"required": ["Id", "Name"]
}
}
}
},
"Reference": {
"type": "object",
"additionalProperties": false,
"properties": {
"Status": { "enum": ["Passed", "Failed"] }
}
}
},
"anyOf": [
{
"not": {
"properties": {
"Reference": {
"properties": {
"Status": { "enum": ["Failed"] }
},
"required": ["Status"]
}
},
"required": ["Reference"]
}
},
{ "not": { "required": ["Payload"] } }
]
}

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" }
]
}
}
}
}