Json Schema template for valiadtion - jsonschema

I am new to defining JSON schema and validating json against the schema.
Here is a sample json for which I want to define a json schema template for validation:
{
 "version": "1.0",
 "config": {
   "globalConfig": {
      “ClientNames”: [
        “client1”, “client2”, “client3”
       ]
    },
“ClientConfigs”: [
{
“ClientName”: “client1”,
“property1”: “some value”,
“property2”: “some value”
},
{
“ClientName”: “client2”,
“property1”: “some value”,
“property2”: “some value”
},
{
“ClientName”: “client3”,
“property1”: “some value”,
“property2”: “some value”
}
]
}
From what I understand “ClientConfigs” would be an array of object (let’s say ClientConfig) which will contain clientName, property1 and property2. Here is what I think schema would like:
{
"$schema": "http://json-schema.org/draft-01/schema#",
"title": "ClientConfig",
"type": "object",
"description": "Some configuration",
"properties": {
"version": {
"type": "string"
},
"config": {
"$ref": "#/definitions/config"
}
},
"definitions": {
"config": {
"type": "object",
"properties": {
"globalConfig": {
"type": "object",
"description": "Global config for all clients",
"properties": {
"ClientNames": {
"type": "array",
"minItems": 1,
"items": {
"type": "string"
}
}
}
},
"ClientConfigs": {
"type": "array",
"description": "List of configs for different clients",
"minItems": 1,
"items": {
"$ref": "#/definitions/ClientConfig"
}
}
}
},
"ClientConfig": {
"type": "object",
"properties": {
"ClientName": {
"type": "string"
},
"property1": {
"type": "string"
},
"property2": {
"type": "string"
}
}
}
}
}
I want to validate 2 things with jsonschema:
ClientName in every element of ClientConfigs array is one of the values from “ClientNames” i.e. individual ClientConfig in “ClientConfigs” array should only contain client names defined in property “ClientNames”.
Every clientName present in “ClientNames” should be defined as an element in “ClientConfigs” array. To be more precise, ClientConfig is defined for every clientName present in “ClientNames” property.
Here is an example which is NOT valid according to my requirements:
{
 "version": "1.0",
 "config": {
   "globalConfig": {
      “ClientNames”: [
        “client1”, “client2”, “client3”
       ]
    },
“ClientConfigs”: [
{
“ClientName”: “client4”,
“property1”: “some value”,
“property2”: “some value”
}
]
}
It is invalid because:
It doesn’t define ClientConfig for client1, client2 and client3.
It defines ClientConfig for client4 which is not present in “ClientNames”.
Is it possible to do such validation using json schema template? If yes, how to validate the same?

You cannot reference instance data in your JSON Schema. This is considered business logic and is out side of the scope for JSON Schema.

Related

Enum inside the Array is not validting in json-schema

I am validating the json with json_schema.
Allowed values for ghrBillingCode should be only "I9NOT"
expected result should be error as 2nd and 3rd node is not I9NOT but it is validating json as correct.
What is wrong in json-schema i am using
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "array",
"items": [
{
"type": "object",
"properties": {
"invoiceLineInfo": {
"type": "array",
"items": [
{
"type": "object",
"properties": {
"ghrBillingCode": {
"type": "string",
"enum": [
"I9NOT"
]
},
"quantity": {
"type": "integer"
}
}
}
]
},
"invoiceNumber": {
"type": "string"
}
}
}
]
}
json:
[
{
"invoiceLineInfo":[
{
"ghrBillingCode":"I9NOT",
"quantity":1
},
{
"ghrBillingCode":"I9NOTRU",
"quantity":2
},
{
"ghrBillingCode":"I9PSUP",
"quantity":1
}
],
"invoiceNumber":"202203010100301"
}
]
In your schema, you have extra brackets [] around the items array type. This means that the enum is checked for the first array element only and your example validates because the first item happens to be "I9NOT".
From your sample document, it seems like you expect the enum to apply to all array elements. To achieve this, simply drop the [] from the items value.
For the array / items syntax, have a look here:
https://json-schema.org/understanding-json-schema/reference/array.html#items

How to ref JSON schema definition of type array with anyOf definition in other files

I have a jsonschema definition definition-1.json like below. I have a property called inputs of type array which refers anyOf definitions like
"inputs": {
"type": "array",
"items": {
"anyOf": [
{
"$ref": "#/definitions/stringParameter"
},
{
"$ref": "#/definitions/numberParameter"
},
{
"$ref": "#/definitions/booleanParameter"
},
{
"$ref": "#/definitions/jsonParameter"
},
{
"$ref": "#/definitions/fileParameter"
}
]
}
}
Then the parameter definitions defined like below in the same jsonschema definition-1.json
"definitions": {
"stringParameter": {
"type": "object",
"required": [
"name",
"description",
"datatype"
]
}
...
}
Now I want to reference this parameter definitions in my other schema dummy-1.json like below
{
"$schema": "http://json-schema.org/draft-07/schema",
"$id": "dummy-1.json",
"allOf": [
{
"type": "object",
"required": [
"definition_data"
],
"properties": {
"definition_data": {
"type": "object",
"required": [
"inputs"
],
"properties": {
"type": "array",
"inputs": {
"items": {
"allOf": [
{
"prop1": {
"$ref": "#/definitions/stringParameter"
}
},
{
"prop2": {
"$ref": "#/definitions/numberParameter"
}
}
]
}
}
}
}
}
},
{
"type": "object",
"properties": {
"definition_data": {
"$ref": "definition-1.json"
}
}
}
]
}
This doesn't looks like working. prop1 will validate successfully for any properties part of other parameter definition too , even though in dummy-1.json I explicitly referred #/definitions/stringParameter .
I can understand inputs in definition-1.json accepts anyOf all parameter definitions. But want to know how we can achieve 1:1 parameter definition mapping for dummy-1.json .
If my understanding is correct, you want to refer from dummy-1.json to subschemas defined in definitions-1.json. To do that, you have to specify the URI of definition-1.json and append the pointer of the subschema in it, like:
dummy-1.json:
{
"$ref": "uri-of-definitions-1.json#/definitions/stringParameter"
}
Note that the URI to be set is quite specific to the json schema library you are using. Usually an absolute https:// URL works, but it isn't always convenient to work with. Maybe a relative path can work for you as well (like ./definition-1.json#/definitions/stringParameter)

Json schema conditional validation configuration - Unsupported keyword(s): ["const"]]

I want to set up the conditional validation in my schema. I saw an example here on SO.
I have a similar setup, where I would like to validate if the field public is set to string "public". If it is set to "public" then I want to make fields description, attachmentUrl and tags required. If the field is not set to "public" then this fields are not required.
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Update todo",
"type": "object",
"properties": {
"public": {
"type": "string"
},
"description": {
"type": "string",
"minLength": 3
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"uniqueItems": true,
"minItems": 1
},
"attachmentUrl": {
"type": "string"
}
},
"anyOf": [
{
"not": {
"properties": {
"public": { "const": "public" }
},
"required": ["public"]
}
},
{ "required": ["description", "tags", "attachmentUrl"] }
],
"additionalProperties": false
}
But, when I try to deploy it like that, I get the following error:
Invalid model specified: Validation Result: warnings : [], errors :
[Invalid model schema specified. Unsupported keyword(s): ["const"]]
The "const" keyword wasn't added until draft 06. You should upgrade to an implementation that supports at least that version.
https://json-schema.org/draft-06/json-schema-release-notes.html#additions-and-backwards-compatible-changes
Otherwise, you can use "enum" with a single value: "enum": ["public"]

Apply addtional constraints to a refered definition in JSON schema

I defined in the schema a validType, where every attribute should have text and annotation .
I want to add additional constraints to refine the text of course must follow "pattern":"[a-z]{2}[0-9]{2}". Is there any way I can apply the constraint directly without copy&paste the content of the validType?
Schema:
{
"type": "object",
"definition": {
"validType": {
"description": "a self-defined type, can be complicated",
"type": "object",
"properties": {
"text": {
"type": "string"
},
"annotation": {
"type": "string"
}
}
},
"properties": {
"name": {
"$ref": "#/definitions/validType"
},
"course": {
"$ref": "#/definitions/validType"
}
}
}
}
Data:
{"name":{
"text":"example1",
"annotation":"example1Notes"},
"course":{
"text":"example2",
"annotation":"example2Notes"}}
The expected schema for course should work as this:
{"course": {
"type": "object",
"properties": {
"text": {
"type": "string",
"pattern":"[a-z]{2}[0-9]{2}"
},
"annotation": {
"type": "string"
}
}
}}
But instead of repeating the big block of validType, I am expecting something similar to the format below:
{"course": {
"$ref": "#/definitions/validType"
"text":{"pattern":"[a-z][0-9]"}
}}
Yup! You can add constraints but you cannot modify the constraints you reference.
To add constraints, you need to understand that $ref for draft-07 and previous is the only allowed key in a subschema when it exsits. Other keys are ignored if it exists.
As such, you need to create two subschemas, one of which has your reference, and the other your additional constraint.
You then wrap these two subschemas in an allOf.
Here's how that would look...
{
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"course": {
"allOf": [
{
"$ref": "#/definitions/validType"
},
{
"properties": {
"text": {
"pattern": "[a-z][0-9]"
}
}
}
]
}
}
}
Have a play using https://jsonschema.dev

Preventing dependent property validation when the parent property does not exist

I am new to JSON schemas. I have a property (property1) that is dependent on another property (property2), which in turn is dependent on a third property (property3). I am trying to figure out how to prevent the schema from validating property1 if property2 doesn't exist. I am using the Python jsonschema module for validating.
I have a simple schema with three properties: species, otherDescription, and otherDescriptionDetail. The rules I'm trying to enforce are:
1) if species = "Human", otherDescription is required.
2) if species = "Human" and otherDescription != "None", otherDescriptionDetail is required.
3) if species != "Human", neither of the other two fields is required.
My test JSON correctly fails validation if species is "Human" and otherDescription doesn't exist, but it also reports that otherDescriptionDetail is a required property even though at this point it shouldn't be because there is no otherDescription value to compare it against. Is it possible to implement this logic with a JSON schema?
This is my schema:
"$schema": "http://json-schema.org/draft-07/schema#",
"$id":"http://example.com/test_schema.json",
"title": "annotations",
"description": "Validates file annotations",
"type": "object",
"properties": {
"species": {
"description": "Type of species",
"anyOf": [
{
"const": "Human",
"description": "Homo sapiens"
},
{
"const": "Neanderthal",
"description": "Cave man"
}
]
},
"otherDescription": {
"type": "string"
},
"otherDescriptionDetail": {
"type": "string"
}
},
"required": [
"species"
],
"allOf": [
{
"if": {
"properties": {
"species": {
"const": "Human"
}
}
},
"then": {
"required": ["otherDescription"]
}
},
{
"if": {
"allOf": [
{
"properties": {
"species": {
"const": "Human"
},
"otherDescription": {
"not": {"const": "None"}
}
}
}
]
},
"then": {
"required": ["otherDescriptionDetail"]
}
}
]
}
My test JSON is:
{
"species": "Human"
}
The output that I want:
0: 'otherDescription' is a required property
The output that I am getting:
0: 'otherDescription' is a required property
1: 'otherDescriptionDetail' is a required property
Any help would be greatly appreciated.
You need to defined otherDescription as a required property insilde allOf. Otherwise allOf block will pass even if otherDescription not available.
"if": {
"allOf": [
{
"properties": {
"species": {
"const": "Human"
},
"otherDescription": {
"not": {"const": "None"}
}
},
"required": ["otherDescription"]
}
]
},
"then": {
"required": ["otherDescriptionDetail"]
}