JSON schema to validate that property name matches nested value - json

We are using JSON to store some configuration settings. For example:
{
"source1": {
"name": "source1",
"standalone": false
},
"source2": {
"name": "source2",
"standalone": true
},
"source3": {
"name": "source3",
"standalone": true
}
}
As you can see, the source names are variable and are repeated for convenience inside the object under a property name.
We're currently validating this using a JSON schema as follows:
{
"$schema": "http://json-schema.org/draft-06/schema#",
"type": "object",
"patternProperties": {
"^\\w[-\\w_]*$": { "$ref": "#/definitions/source" }
},
"additionalProperties": false,
"definitions": {
"source": {
"type": "object",
"properties": {
"name": { "type": "string" },
"standalone": { "type": "boolean" }
},
"required": ["name", "standalone"],
"additionalProperties": false
}
}
}
Is there a way to require that the property name matches the value using JSON schema? In other words, is there a way to make sure the following example fails to validate?
{
"a": {
"name": "b",
"standalone": false
}
}

Related

JSON Schema object contains value

I want to check that "obj" contains at least one value "test". But keys in the "obj" are random.
Json:
{
"title": "doc",
"obj": {
"xxxx-random": "test",
"zzzz-random": "wol"
}
}
My idea was to use oneOf but it doesn't work as I expected:
Schema Json:
{
"properties": {
"title": {
"type": "string"
},
"obj": {
"type": "object",
"oneOf": [
{
"contains": {
"properties": {
"type": "string",
"desc":"test"
}
}
}
]
}
}
}
You can do that with slightly-mindbending uses of the "not" keyword. That is, we can construct a schema that asserts:
the property "obj" must exist
"obj"'s value is an object, and there must be at least one property
and it cannot be true that all properties under "obj" do NOT match "test"
{
"type": "object",
"required": ["obj"],
"properties": {
"obj": {
"type": "object",
"minProperties": 1,
"not": {
"additionalProperties": { "not": { "const": "test" } }
}
}
}
}

Json Schema matching with 'anyOf'

I'd like to be able to manage a json array of 'objects' where each object has a type and properties, and there's a schema error if a mandatory property is missing from an object.
This is my attempt to do this (not including the array part) declaring two object types and saying the object in the json can be either of those types:
{
'definitions':
{
'typeone':
{
'type': 'object',
'properties':
{
'xtype': {'type':'string', 'const':'typeone'},
'num' : {'type':'number'}
},
'required':['xtype', 'num'],
'additionalProperties':false
},
'typetwo':
{
'type': 'object',
'properties':
{
'xtype': {'type':'string', 'const':'typetwo'},
'str' : {'type':'string'}
},
'required':['xtype', 'str'],
'additionalProperties':false
}
},
'anyOf':
[
{ '$ref': '#/definitions/typeone' },
{ '$ref': '#/definitions/typetwo' },
]
}
However, if I feed it json which fails because a mandatory property is missing from an object like this:
{
'xtype': 'typeone'
}
...it errors with JSON does not match any schemas from 'anyOf'. - I can see the reason is that it doesn't know to try to match on the xtype, instead it just considers xtype of 'typeone' invalid and looks to others.
Is there a better way to do anyOf which will hard-match based on one property value (like a 'switch') then give errors about missing other mandatory properties for that object type?
It gets a lot more verbose, but you can use if/then to switch validation based on the "xtype" property.
{
"$schema": "http://json-schema.org/draft-07/schema#",
"allOf": [
{
"if": {
"type": "object",
"properties": {
"xtype": { "const": "typeone" }
},
"required": ["xtype"]
},
"then": { "$ref": "#/definitions/typeone" }
},
{
"if": {
"type": "object",
"properties": {
"xtype": { "const": "typetwo" }
},
"required": ["xtype"]
},
"then": { "$ref": "#/definitions/typetwo" }
}
],
"definitions": {
"typeone": {
"type": "object",
"properties": {
"xtype": {},
"num": { "type": "number" }
},
"required": ["num"],
"additionalProperties": false
},
"typetwo": {
"type": "object",
"properties": {
"xtype": {},
"str": { "type": "string" }
},
"required": ["str"],
"additionalProperties": false
}
}
}
With a small change to the model, you could use dependencies to get a much simpler cleaner schema. Instead of having an "xtytpe" property, you can have a property corresponding to the name of the type. For example, { "typeone": true }.
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"dependencies": {
"typeone": {
"type": "object",
"properties": {
"typeone": {},
"num": { "type": "number" }
},
"required": ["num"],
"additionalProperties": false
},
"typetwo": {
"type": "object",
"properties": {
"typetwo": {},
"str": { "type": "string" }
},
"required": ["str"],
"additionalProperties": false
}
}
}

Json schema for recursive structure not working

Here is my json schema. I want a recursive tree-like structure. But the response is passing even when I have invalid objects in the required array.
{
"$schema":"http://json-schema.org/draft-03/schema",
"properties":{
"Result":{
"type":"object",
"properties":{
"Children":{
"$ref":"#/definitions/Node"
}
},
"required":true
}
},
"required":true,
"type":"object",
"definitions":{
"Node":{
"type":"array",
"Items":{
"type":"object",
"properties":{
"Children":{
"$ref":"#/definitions/Node"
}
},
"required":true
}
}
}
}
To check that the JSON Schema validation will validate correctly , I deliberately put an invalid object inside the response -
{"Result":{"title":"title","Children":[{"invalidobject":"invalidobject"}]}}
But it is passing here - https://www.jsonschemavalidator.net/
What I actually want is Children to also have an array of Children and so on. So, only Children having objects with properties - title and Children should be allowed.
Its passing for this response too -
{"Result":{"title":"title","Children":[{"title":45}]}}
Try this schema. Note that this schema will allow children array to be empty even on the first level. After the first level, you have to allow children array to be empty otherwise, the schema will expect infinitely recursive data in order to pass validation.
{
"$schema": "http://json-schema.org/draft-03/schema",
"type": "object",
"properties": {
"Result": {
"$ref": "#/definitions/node",
"required":true,
}
},
"definitions": {
"node": {
"type": "object",
"properties": {
"title": {
"type": "string",
"required": true
},
"Children": {
"type": "array",
"required": true,
"items": {
"$ref": "#/definitions/node"
}
}
},
"additionalProperties": false
}
}
}
In case you do not want to allow children array to be empty at first level try defining the first level separately like this.
{
"$schema": "http://json-schema.org/draft-03/schema",
"type": "object",
"properties": {
"Result": {
"type": "object",
"required": true,
"properties": {
"title": {
"$ref": "#/definitions/title"
},
"Children": {
"minItems": 1,
"$ref": "#/definitions/Children"
}
},
"additionalProperties": false
}
},
"definitions": {
"title": {
"type": "string",
"required": true
},
"Children": {
"type": "array",
"required": true,
"items": {
"$ref": "#/definitions/node"
}
},
"node": {
"type": "object",
"properties": {
"title": {
"$ref": "#/definitions/title"
},
"Children": {
"$ref": "#/definitions/Children"
}
},
"additionalProperties": false
}
}
}
Here the validation results for sample input JSONs validated from https://www.jsonschemavalidator.net/
Input JSON:
{
"Result": {
"title": "title",
"Children": [
{
"invalidobject": "invalidobject"
}
]
}
}
Validation result:
Message:
Property 'invalidobject' has not been defined and the schema does not allow additional properties.
Schema path:
#/definitions/node/additionalProperties
Message:
Required properties are missing from object: title, Children.
Schema path:
#/definitions/node/required
Inpot JSON:
{
"Result": {
"title": "title",
"Children": [
{
"title": 45
}
]
}
}
Validation result:
Message:
Invalid type. Expected String but got Integer.
Schema path:
#/definitions/node/properties/title/type
Message:
Required properties are missing from object: Children.
Schema path:
#/definitions/node/required

JSON Schema validation using tv4 or any other validator

I have a some kind JSON structure within an array. The requirement is:
1. All the JSON object within the array can be optional.
2. Each JSON can have its own set of properties and can be complex and nested.
3. Each JSON object will have a set of mandatory attributes.
How to create a schema for such JSON. Will uisng anyOf or definitions will be helpful?
Updated: I have an array of JSON objects, where each object can have different attributes. The only attribute that will be common is 'type' with valid values as: electronics or furniture or finance. So my question is how to derive a schema?
Example
{
"list": [
{
"type": "electronics"
},
{
"type": "furniture"
},
{
"accessRights": "readOnly",
"rules": ['print','copy'],
"type": "finance"
}
}
Solution
{
"properties": {
"list": {
"type": "array",
"items": {
"type": "object",
"required": ["type"],
"properties": {
"type": {
"type": "string",
"enum": ["electronics", "furniture", "finance"]
}
},
"anyOf": [{
"properties": {
"type": {
"enum": ["electronics"]
}
}
}, {
"properties": {
"type": {
"enum": ["furniture"]
}
}
}, {
"properties": {
"type": {
"enum": ["finance"]
},
"accessRights": {
"type": "string"
},
"rules": {
"type": "array"
}
}
}]
}
}
}
}

JSON schema validation with Map of string with Enum constraints

Requesting help with JSON Schema validation, below is sample JSON and Schema. I am trying to figure out how to specify "ppd" schema rule specifically "cfg" is a map of String, String and need to further restrict the entries of the key and value in this map by Enum definition i.e. allowed values for "inputDateTimeFormat" is a valid date time format so rule should encode if key is "inputDateTimeFormat" then allowed value is a pattern matching date time format and similarly if key is "valuemapping" then allowed values is pattern matching k=v (example below).
Could you please suggest a way to achieve this?
JSON Sample -
{
"sm": [
{
"mid": "id-1",
"ppd": [
{
"name": "cc-1",
"cfg": {
"columns": "v-1",
"valueMapping": "B=01;S=02"
}
},
{
"name": "cc-2",
"cfg": {
"columns": "v-2",
"inputDateTimeFormat": "ddMMMyyyy_HH:mm:ss.SSSSSS",
"outputDateTimeFormat": "yyyy-MM-dd'T'HH:mm:Ss.SSSZ"
}
},
{
"name": "cc-3",
"cfg": {
"columns": "v-3;v-4",
"markers": "d=01"
}
}
]
}
]
}
JSON Schema :
{
"type": "object",
"$schema": "http://json-schema.org/draft-06/schema",
"id": "source-mappings-schema",
"required": true,
"properties": {
"sm": {
"type": "array",
"id": "source-mappings-schema/sm",
"required": true,
"items": {
"type": "object",
"id": "source-mappings-schema/sm/0",
"required": true,
"properties": {
"mappingId": {
"type": "string",
"id": "source-mappings-schema/sm/0/mappingId",
"required": true
},
"ppd": {
"type": "array",
"id": "source-mappings-schema/sm/0/ppd",
"required": true,
"items": {
"type": "object",
"id": "source-mappings-schema/sm/0/ppd/0",
"required": true,
"properties": {
"name": {
"type": "string",
"id": "source-mappings-schema/sm/0/ppd/0/name",
"required": true
},
"cfg": {
"type": "array",
"id": "source-mappings-schema/sm/0/ppd/0/cfg",
"required": true,
"items": {
"type": "string"
}
}
}
}
}
}
}
}
}
}
To start with your schema contains a few issue.
The $schema tag is wrong, it should be
"$schema": "http://json-schema.org/draft-06/schema#",
The 'required' property is supposed to be an array of property names that are required (not a bool), so you need to apply this at the level above.
Finally the validation of cfg. By specifying a schema for 'additionalProperties' you can provide validation rules for all unspecified key values (you said it was a map of strings, so I've set it to string, but you could also add other rules here like max length etc).
For the keys you know about you can add a property for each of them with the approrate validation rules (the rules i've added demonstrate the concept and will need tweaking for your use).
"cfg": {
"type": "object",
"additionalProperties": {
"type": "string"
},
"properties": {
"inputDateTimeFormat": {
"type": "string",
"format": "date-time"
},
"valuemapping": {
"type": "string",
"pattern": "[a-z]\\=[a-z]"
}
}
}