JSON schema does not validate missing properties - json

Thanks for your help in advance. Its my bad day.
I have the following json and I am trying to figure out the schema for it. Unfortunately, I was stuck at a point with no sign of error.
Please advise the solution
{
"tables_not_to_mask": ["Table_1"],
"tables_to_mask":{
"Table_2": [
{
"column": "BinLogFilename",
"masking_type": "replace_logfilename"
},
{
"column": "ServerId",
"masking_type": "replace_server_id"
}
],
"Table_3": [
{
"column": "BinLogFilename",
"masking_type": "replace_logfilename"
},
{
"column": "ServerId",
"masking_type": "replace_server_id"
}
]
}
}
The Table_1,Table_2,.. are dynamically added. I have created schema that should validate JSON input in the following,
tables_not_to_mask and tables_to_mask are required.
tables_to_mask can have zero or more tables
If there is table in tables_to_mask, it can have zero to many column and masking_type defined.
column and masking_type are mandatory and no one is single.
I created the schema for it and unfortunately, if i remove column or masking_type, the schema does not throw any error.
{
"title": "Schema title",
"description": "Description of the schema",
"type": "object",
"properties": {
"tables_not_to_mask": {
"type": "array",
"minItems": 0,
"items": {"type": "string"}
},
"tables_to_mask": {
"type": "object",
"patternProperties": {
".*": {
"type": "array",
"minItems": 0,
"properties": {
"column": {"type": "string"},
"masking_type": {"type": "string"}
},
"required": [
"masking_type",
"column"
]
}
}
}
},
"required": [
"tables_not_to_mask",
"tables_to_mask"
]
}

Finally, I got the answer. Thanks for looking into it.
{
"$schema": "https://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"tables_not_to_mask":
{"$ref": "#/definitions/tables_not_to_mask_type"},
"tables_to_mask":
{"$ref": "#/definitions/tables_to_mask_type"}
},
"required": [
"tables_not_to_mask",
"tables_to_mask"
],
"definitions": {
"tables_not_to_mask_type": {
"type": "array",
"minItems": 0,
"items": {"type": "string"}
},
"tables_to_mask_type": {
"type": "object",
"patternProperties": {
".*": {"$ref": "#/definitions/tables_type"}
}
},
"tables_type": {
"type": "array",
"minItems": 0,
"items": {
"type": "object",
"properties": {
"column": {"type": "string"},
"masking_type": {"type": "string"}
},
"required": [
"masking_type",
"column"
]
}
}
}
}

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 definition using conditional statements

Iam trying to define an optional condition using json schema conditional statement (Using draft 7)
I have a json response like this.
[{
"views": [{
"name": "RSO Roster",
"displayOrder": 5,
"groups": [{
"type": "scrollable",
"displayOrder": 1,
"auditType": "player-pregame_roster",
"tiles": [{
"context": "event",
"dataStamp": 1535184247,
"tile_type": "person"
}, {
"context": "event",
"errorCode": 2,
"errorText": "seloger",
"tile_type": "person"
}
]
}
]
},
{
"name": "Leaders",
"displayOrder": 1,
"groups": [{
"type": "static",
"displayOrder": 1,
"tiles": [{
"context": "event",
"dataStamp": 1535184247,
"eventId":123
"tile_type": "static"
}
]
}
]
}
]
}]
In this response if the tile object contains the key errorCode the required field must be errorText and errorCode keys.Like wise
if the tile object doessnot contains any "errorCode" or "errorText" key then the tile item contains the required field "dataStamp".
To validate the above condition i have defined a schema like below.But it is not working.Whats wrong with my schema .
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "array",
"items": {
"type": "object",
"properties": {
"views": {
"$id": "views",
"type": "array",
"items": {
"$id": "views/items",
"type": "object",
"properties": {
"groups": {
"$id": "views/groups",
"type": "array",
"items": {
"$id": "views/groups/items",
"type": "object",
"properties": {
"tiles": {
"$id": "views/groups/tiles",
"type": "array",
"items": {
"$id": "views/groups/tiles/items",
"type": "object",
"properties": {
"dataStamp": {
"$id": "views/groups/tiles/dataStamp",
"type": "integer"
},
"tile_type": {
"$id": "views/groups/tiles/tile_type",
"type": "string"
},
"errorCode": {
"type": "integer",
"enum": [
2, 10
]
},
"errorText": {
"type": "string",
"enum": [
"seloger", "france24"
]
}
},
"if": {
"properties": {
"tile_type": {
"enum": ["person"]
},
"errorCode": {
"enum": [2, 10]
}
},
"required": ["errorCode", "errorText"]
}
}
}
},
"required": [
"type",
"tiles"
]
}
}
},
"required": [
"groups"
]
}
}
},
"required": [
"views"
]
}
}
The if statement is missing required in properties:
"if": {
"properties": {
"tile_type": {
"enum": ["person"]
},
"errorCode": {
"enum": [2, 10]
},
"required": ["errorCode"]
}
},
If there is no required the value of property is validated only if the property is set. So original if schema would pass any object without tile_type and errorCode.
https://stackoverflow.com/a/51034071/329463 might give you some inspiration on building exclusive properties clusters.
EDIT: modified full schema
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "array",
"items": {
"type": "object",
"properties": {
"views": {
"$id": "views",
"type": "array",
"items": {
"$id": "views/items",
"type": "object",
"properties": {
"groups": {
"$id": "views/groups",
"type": "array",
"items": {
"$id": "views/groups/items",
"type": "object",
"properties": {
"tiles": {
"$id": "views/groups/tiles",
"type": "array",
"items": {
"$id": "views/groups/tiles/items",
"type": "object",
"properties": {
"dataStamp": {
"$id": "views/groups/tiles/dataStamp",
"type": "integer"
},
"tile_type": {
"$id": "views/groups/tiles/tile_type",
"type": "string"
},
"errorCode": {
"type": "integer",
"enum": [
2, 10
]
},
"errorText": {
"type": "string",
"enum": [
"seloger", "france24"
]
}
},
"if": {
"properties": {
"tile_type": {
"enum": ["person"]
},
"errorCode": {
"enum": [2, 10]
}
},
"required":["errorCode"]
},
"then": {
"required": ["errorCode", "errorText"]
},
"else": {
"required": ["dataStamp"]
}
}
}
},
"required": [
"type",
"tiles"
]
}
}
},
"required": [
"groups"
]
}
}
},
"required": [
"views"
]
}
}

JsonSchema: Validate type based on value of another property

I am using the following schema to validate my json:
{
"$schema": "http://json-schema.org/schema#",
"title": " Rules",
"description": "Describes a set of rules",
"type": "object",
"properties": {
"rules": {
"type": "array",
"items": {
"type": "object",
"properties": {
"precedence": {
"type": "number",
"minimum": 0
},
"conditions": {
"type": "array",
"items": {
"type": "object",
"properties": {
"field": {
"type": "string",
"enum": [ "Name", "Size" ]
},
"relation": {
"type": "string",
"enum": [ "is", "is not", "is not one of", "is one of" ]
},
"value": {
"type": ["array", "string", "number"]
}
},
"required": ["field", "relation", "value"],
"additionalProperties": false
}
}
},
"required": ["precedence", "conditions"],
"additionalProperties": false
}
}
},
"required": ["rules"],
"additionalProperties": false
}
I want to set up a dependency to validate that when the value of the relation property has the value is one of or the value is not one of, then the type of the value property can only be array
For example, the following json should not validate because it uses the relation value is not one of and the value property is not an array:
{
"rules": [{
"precedence": 0,
"conditions": [{
"field": "Name",
"relation": "is not one of",
"value": "Mary"
}
]
}
]
}
Is it possible to set up dependencies to validate this way?
The best way to solve these kinds of problems is to separate the complex validation from the rest of the schema using definitions and include it with an allOf. In this solution, I use implication to enforce the validation.
{
"type": "object",
"properties": {
"rules": {
"type": "array",
"items": { "$ref": "#/definitions/rule" }
}
},
"required": ["rules"],
"definitions": {
"rule": {
"type": "object",
"properties": {
"precedence": { "type": "number", "minimum": 0 },
"conditions": {
"type": "array",
"items": { "$ref": "#/definitions/condition" }
}
},
"required": ["precedence", "conditions"]
},
"condition": {
"type": "object",
"properties": {
"field": { "enum": ["Name", "Size"] },
"relation": { "enum": ["is", "is not", "is not one of", "is one of"] },
"value": { "type": ["array", "string", "number"] }
},
"required": ["field", "relation", "value"],
"allOf": [{ "$ref": "#/definitions/array-condition-implies-value-is-array" }]
},
"array-condition-implies-value-is-array": {
"anyOf": [
{ "not": { "$ref": "#/definitions/is-array-condition" } },
{ "$ref": "#/definitions/value-is-array" }
]
}
"is-array-condition": {
"properties": {
"relation": { "enum": ["is not one of", "is one of"] }
},
"required": ["relation"]
},
"value-is-array": {
"properties": {
"value": { "type": "array" }
}
}
}
}
If you are able to use the latest draft-7 version of JSON Schema, you can use if then else, as per https://datatracker.ietf.org/doc/html/draft-handrews-json-schema-validation-00#section-6.6
Although, using oneOf is also a valid approach, it might not be as clear to someone else inspecting your schema at a later date.
I've copied an example from an answer to another question:
If the "foo" property equals "bar", Then the "bar" property is
required
{
"type": "object",
"properties": {
"foo": { "type": "string" },
"bar": { "type": "string" }
},
"if": {
"properties": {
"foo": { "enum": ["bar"] }
}
},
"then": { "required": ["bar"] }
}
(You may want to check the draft support of the library you are using.)
There may be a more concise way to do this, but this will work:
{
"$schema": "http://json-schema.org/schema#",
"title": "Rules",
"description": "Describes a set of rules",
"definitions": {
"field": {
"type": "string",
"enum": ["Name", "Size"]
}
},
"type": "object",
"properties": {
"rules": {
"type": "array",
"items": {
"type": "object",
"properties": {
"precedence": {
"type": "number",
"minimum": 0
},
"conditions": {
"type": "array",
"items": {
"type": "object",
"oneOf": [
{
"properties": {
"field": {
"$ref": "#/definitions/field"
},
"relation": {
"type": "string",
"enum": ["is", "is not"]
},
"value": {
"type": ["string", "number"]
}
},
"required": ["field", "relation", "value"],
"additionalProperties": false
},
{
"properties": {
"field": {
"$ref": "#/definitions/field"
},
"relation": {
"type": "string",
"enum": ["is not one of", "is one of"]
},
"value": {
"type": ["array"]
}
},
"required": ["field", "relation", "value"],
"additionalProperties": false
}
]
}
}
},
"required": ["precedence", "conditions"],
"additionalProperties": false
}
}
},
"required": ["rules"],
"additionalProperties": false
}

How to reference json schema definition from another schema

I have a json schema representing a geometry as a Point or a MultiPoint. Each is defined within the schema in "definitions":
{
"$schema": "http://json-schema.org/draft-04/schema#",
"id": "http://schema.my-site.org/geometry.json#",
"type": "object",
"oneOf": [
{
"allOf": [
{
"required": [
"type",
"coordinates"
]
},
{
"oneOf": [
{
"$ref": "#/definitions/Point"
},
{
"$ref": "#/definitions/MultiPoint"
}
]
}
]
}
],
"definitions": {
"Point": {
"title": "Point",
"type": "object",
"properties": {
"type": {
"enum": [
"Point"
]
},
"coordinates": {
"$ref": "#/definitions/position"
}
}
},
"MultiPoint": {
"title": "MultiPoint",
"type": "object",
"properties": {
"type": {
"enum": [
"MultiPoint"
]
},
"coordinates": {
"$ref": "#/definitions/positionArray"
}
}
},
"position": {
"type": "array",
"minItems": 2,
"maxItems": 2,
"additionalItems": false,
"items": [
{
"type": "number"
},
{
"type": "number"
}
]
},
"positionArray": {
"type": "array",
"items": {
"$ref": "#/definitions/position"
}
}
}
}
Now I want to make another schema, which makes use of the Point definition. Currently, I copypasted the definitions for Point and position in the properties "startPosition" and "endPosition" and it works. But is there a way how to just reference the Point's definition from my geometry.json schema?
note: I only want to allow Point to be used here but not a MultiPoint - A geometry.json ref would allow both instead.
{
"$schema": "http://json-schema.org/draft-04/schema#",
"id": "http://schema.my-site.org/myitem.json#",
"type": "object",
"additionalProperties": false,
"required": [
"myproperty"
],
"properties": {
"myproperty": {
"type": "array",
"minItems": 0,
"items": {
"type": "object",
"additionalProperties": false,
"properties": {
"id": {
"type": "string"
},
"startPosition": {
"geometry": {
"required": [
"type",
"coordinates"
],
"title": "Point",
"type": "object",
"properties": {
"type": {
"enum": [
"Point"
]
},
"coordinates": {
"type": "array",
"minItems": 2,
"maxItems": 2,
"additionalItems": false,
"items": [
{
"type": "number"
},
{
"type": "number"
}
]
}
}
}
},
"endPosition": {
"geometry": {
"required": [
"type",
"coordinates"
],
"title": "Point",
"type": "object",
"properties": {
"type": {
"enum": [
"Point"
]
},
"coordinates": {
"type": "array",
"minItems": 2,
"maxItems": 2,
"additionalItems": false,
"items": [
{
"type": "number"
},
{
"type": "number"
}
]
}
}
}
}
}
}
}
}
}
Haven't tested it myself, but according to this, you can make use of JSON pointers:
In file geometry.json:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"id": "http://schema.my-site.org/geometry.json",
"type": "object",
"definitions": {
"Point": { ...},
"MultiPoint": {...}
}
}
In file myitem.json:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"id": "http://schema.my-site.org/myitem.json#",
"type": "object",
"properties": {
"point": {
"$ref": "http://schema.my-site.org/geometry.json#definitions/Point"
}
}
}

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