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?
Related
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"] } }
]
}
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"]
}
I'm using the JSON.Net schema validation package and I've come across a very strange issue. I have tracked down the issue to a use of anyOf in the anyObject definition below:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "http://example.com/schemas/example/1.0/schema.json",
"anyOf": [
{
"$ref": "#/definitions/anyObject"
}
],
"definitions": {
"anyObject": {
"type": "object",
"properties": {
"type": {
"type": "string"
}
},
"required": [
"type"
],
"anyOf": [
{
"if": {
"properties": {
"type": {
"const": "typeA"
}
}
},
"then": {
"$ref": "#/definitions/typeA"
},
"else": false
},
{
"if": {
"properties": {
"type": {
"const": "typeB"
}
}
},
"then": {
"$ref": "#/definitions/typeB"
},
"else": false
}
]
},
"bodyDefinition": {
"oneOf": [
{
"if": {
"properties": {
"$computed": {
"type": "string"
}
},
"required": [
"$computed"
]
},
"then": {
"$ref": "#/definitions/computedBody"
},
"else": {
"$ref": "#/definitions/wildcardBody"
}
},
{
"type": "string"
}
]
},
"wildcardBody": {
"type": "object",
"additionalProperties": {
"$ref": "#/definitions/bodyDefinition"
}
},
"firstComputedValue": {
"type": "object",
"additionalProperties": false,
"properties": {
"$computed": {
"const": "first"
},
"values": {
"type": "array",
"minItems": 1,
"items": {
"$ref": "#/definitions/bodyDefinition"
}
}
},
"required": [
"$computed",
"values"
]
},
"computedBody": {
"oneOf": [
{
"if": {
"properties": {
"$computed": {
"const": "first"
}
}
},
"then": {
"$ref": "#/definitions/firstComputedValue"
},
"else": false
}
]
},
"typeA": {
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"type": "string",
"const": "typeA"
},
"body": {
"$ref": "#/definitions/bodyDefinition"
}
},
"required": [
"type"
]
},
"typeB": {
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"type": "string",
"const": "typeB"
},
"body": {
"$ref": "#/definitions/bodyDefinition"
}
},
"required": [
"type"
]
}
}
}
When I test this json:
{
"type": "typeB",
"body":{
"$computed":"first",
"values":[]
}
}
It should be marked as invalid, because values is required to have at least one value. However it is valid. The below JSON should be considered valid, and the above schema does assert that correctly:
{
"type": "typeB",
"body":{
"$computed":"first",
"values":["foo"]
}
}
If I remove typeA from the anyObject definition, then the validation is performed correctly. Below is the schema that validates correctly:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "http://example.com/schemas/example/1.0/schema.json",
"anyOf": [
{
"$ref": "#/definitions/anyObject"
}
],
"definitions": {
"anyObject": {
"type": "object",
"properties": {
"type": {
"type": "string"
}
},
"required": [
"type"
],
"anyOf": [
{
"if": {
"properties": {
"type": {
"const": "typeB"
}
}
},
"then": {
"$ref": "#/definitions/typeB"
},
"else": false
}
]
},
"bodyDefinition": {
"oneOf": [
{
"if": {
"properties": {
"$computed": {
"type": "string"
}
},
"required": [
"$computed"
]
},
"then": {
"$ref": "#/definitions/computedBody"
},
"else": {
"$ref": "#/definitions/wildcardBody"
}
},
{
"type": "string"
}
]
},
"wildcardBody": {
"type": "object",
"additionalProperties": {
"$ref": "#/definitions/bodyDefinition"
}
},
"firstComputedValue": {
"type": "object",
"additionalProperties": false,
"properties": {
"$computed": {
"const": "first"
},
"values": {
"type": "array",
"minItems": 1,
"items": {
"$ref": "#/definitions/bodyDefinition"
}
}
},
"required": [
"$computed",
"values"
]
},
"computedBody": {
"oneOf": [
{
"if": {
"properties": {
"$computed": {
"const": "first"
}
}
},
"then": {
"$ref": "#/definitions/firstComputedValue"
},
"else": false
}
]
},
"typeA": {
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"type": "string",
"const": "typeA"
},
"body": {
"$ref": "#/definitions/bodyDefinition"
}
},
"required": [
"type"
]
},
"typeB": {
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"type": "string",
"const": "typeB"
},
"body": {
"$ref": "#/definitions/bodyDefinition"
}
},
"required": [
"type"
]
}
}
}
Can anyone see if there is an issue with this definition, or is this an issue with the JSON.Net schema package?
This testing was done against the online version of the schema validator at https://www.jsonschemavalidator.net/
I think this is a bug. I'll speak to the library author about it!
To debug, I followed the validation process through the schema, setting $ref or then or else to false... when I reached computedBody, I changed it to the following...
"computedBody": {
"if": {
"properties": {
"$computed": {
"const": "first"
}
}
},
"then": false,
"else": false
}
Validation still comes back positive, which shouldn't be possible. I proved it reaches computedBody by setting that subschema to false and seeing validation come back negative.
(the oneOf wrapping the subschema of computedBody isn't needed. if is valid at the schema level just fine).
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"] }
}
}
}
}
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" }
]
}
}
}
}