JSON Enum Schema issue - Correct me with valid schema - json

I have following JSON Payload where i am trying to add ENUM type Value for one of the element.
{
"firstName" : "firstName",
"lastName" : "lastName",
"systemIds" : [ {
"systemName" : "SAP",
"systemId" : "99c27c63-e0b6-4585-8675-7aa3811eb4c3"
}, {
"systemName" : "SFDC",
"systemId" : "b65abf1d-825d-4ee3-9791-02d2cdd5e6f4"
}, {
"systemName" : "MONGODB",
"systemId" : "18e50430-8589-42d6-8477-58839a8bf202"
} ]
}
And here is my Schema which i tried to modify after it was auto generated using this website. http://jsonschema.net/#/
I added manually ENUM types as per my expectation here. Please correct what's wrong with this SCHEMA.
{
"$schema": "http://json-schema.org/draft-04/schema#",
"id": "http://abcd.com/schemas/customerInfo",
"type": "object",
"properties": {
"firstName": {
"id": "http://abcd.com/schemas/customerInfo/firstName",
"type": "string"
},
"lastName": {
"id": "http://abcd.com/schemas/customerInfo/lastName",
"type": "string"
},
"systemIds": {
"id": "http://abcd.com/schemas/customerInfo/systemIds",
"type": "array",
"minItems": 1,
"uniqueItems": false,
"additionalItems": true,
"items": {
"anyOf": [
{
"id": "http://abcd.com/schemas/customerInfo/systemIds/0",
"type": "object",
"properties": {
"systemName": {
"id": "http://abcd.com/schemas/customerInfo/systemIds/0/systemName",
"type": { "enum": [ "SAP", "MONGODB", "ERP", "SFDC" ] }
},"required": ["type"],
"systemId": {
"id": "http://abcd.com/schemas/customerInfo/systemIds/0/systemId",
"type": "string"
}
}
}
]
}
}
}
}

The the schema for the array items doesn't look right.
{
"anyOf": [
{
"id": "http://abcd.com/schemas/customerInfo/systemIds/0",
"type": "object",
"properties": {
"systemName": {
"id": "http://abcd.com/schemas/customerInfo/systemIds/0/systemName",
"type": {
"enum": [
"SAP",
"MONGODB",
"ERP",
"SFDC"
]
}
},
"required": [
"type"
],
"systemId": {
"id": "http://abcd.com/schemas/customerInfo/systemIds/0/systemId",
"type": "string"
}
}
}
]
}
You stated that there should be a "required" property but you put in an invalid schema. That needs to be removed. But perhaps you meant that the "type" property is required somewhere and is misplaced. I don't see any relation.
The "systemName" property is a string type with values that should be within that enumeration. The schema there is invalid.
This should work for you:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"id": "http://abcd.com/schemas/customerInfo",
"type": "object",
"properties": {
"firstName": {
"id": "http://abcd.com/schemas/customerInfo/firstName",
"type": "string"
},
"lastName": {
"id": "http://abcd.com/schemas/customerInfo/lastName",
"type": "string"
},
"systemIds": {
"id": "http://abcd.com/schemas/customerInfo/systemIds",
"type": "array",
"minItems": 1,
"uniqueItems": false,
"additionalItems": true,
"items": {
"anyOf": [
{
"id": "http://abcd.com/schemas/customerInfo/systemIds/0",
"type": "object",
"properties": {
"systemName": {
"id": "http://abcd.com/schemas/customerInfo/systemIds/0/systemName",
"type": "string",
"enum": [ "SAP", "MONGODB", "ERP", "SFDC" ]
},
"systemId": {
"id": "http://abcd.com/schemas/customerInfo/systemIds/0/systemId",
"type": "string"
}
}
}
]
}
}
}
}

Related

Items object should have equal property

I have a JSON like this:
{
"result": [
{
"name": "Adam",
"age": 22
},
{
"name": "John"
},
{
"name": "Justin",
"age": 25
}
]
}
and schema:
{
"definitions": {},
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://example.com/object1607582431.json",
"title": "Root",
"type": "object",
"required": [
"result"
],
"properties": {
"result": {
"$id": "#root/result",
"title": "Result",
"type": "array",
"default": [],
"items": {
"$id": "#root/result/items",
"title": "Items",
"type": "object",
"required": [
"name"
],
"properties": {
"name": {
"$id": "#root/result/items/name",
"title": "Name",
"type": "string",
"default": "",
"pattern": "^.*$"
},
"age": {
"$id": "#root/result/items/age",
"title": "Age",
"type": "integer",
"default": 0
}
}
}
}
}
}
Here age is an optional property. I am struggling to apply a rule if an optional property is present in one object then it should present in all the objects in that collection. Is there any option available for this?
This is actually a really good use case for the if/then construct that really can't be replicated by using a oneOf like a switch statement. (Well done.)
You're going to want to add the if/then construct to the results property subschema. If the if passes, then the then MUST also apply.
"result": {
...,
"if": {
"contains": { "required": [ "age" ] } // 1
},
"then": {
"items": { "required": [ "age" ] } // 2
}
}
If the the result object contains an item that has an age property,
Require all items to have an age property.
Edit
Full schema:
{
"definitions": {},
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://example.com/object1607582431.json",
"title": "Root",
"type": "object",
"required": [
"result"
],
"properties": {
"result": {
"$id": "#root/result",
"title": "Result",
"type": "array",
"default": [],
"if": { "contains": { "required": [ "age" ] } },
"then": { "items": { "required": [ "age" ] } },
"items": {
"$id": "#root/result/items",
"title": "Items",
"type": "object",
"required": [
"name"
],
"properties": {
"name": {
"$id": "#root/result/items/name",
"title": "Name",
"type": "string",
"default": "",
"pattern": "^.*$"
},
"age": {
"$id": "#root/result/items/age",
"title": "Age",
"type": "integer",
"default": 0
}
}
}
}
}
}
Instance:
{
"result": [
{
"name": "one"
},
{
"name": "two",
"age": 5
},
{
"name": "three"
}
]
}
Remove the age property or add it to the other items to get the schema to pass.

JSON is not getting validated based on schema

I must be missing something here, but the below JSON is not getting validated against the schema.
For example, the required attribute from the Java/JavaScript object is never getting enforced as per the schema. (FYI- Every language object may have other attributes or nested object)
However, if I completely remove the definition and directly put under array items each separately, then it validates.
I want to use 'definitions' and gets validated.The reason I have to put all the object in definitions and later I may have to put different language object in oneOf/allOf for other certain validation check.
Online check:
Schema and JSON
JSON
{
"languages": [
{
"lang": "Java",
"trainer": "Peter"
},
{
"lang": "JavaScript",
"enrolled": "42",
"available": "5"
}
]
}
and the Schema
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": [
"languages"
],
"properties": {
"languages": {
"type": "array",
"minItems": 1,
"items": {
"type": "object"
},
"anyOf": [
{
"$ref": "#/definitions/Java"
},
{
"$ref": "#/definitions/JavaScript"
}
]
}
},
"definitions": {
"Java": {
"required": [
"trainer"
],
"properties": {
"lang": {
"enum": [
"Java"
]
},
"trainer": {
"type": "string"
}
}
},
"JavaScript": {
"required": [
"enrolled",
"available"
],
"properties": {
"lang": {
"enum": [
"JavaScript"
]
},
"enrolled": {
"type": "string"
},
"available": {
"type": "string"
}
}
}
}
}
The fixed schema and it works now
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": [
"languages"
],
"properties": {
"languages": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"anyOf": [
{
"$ref": "#/definitions/Java"
},
{
"$ref": "#/definitions/JavaScript"
}
]
}
}
},
"definitions": {
"Java": {
"required": [
"trainer"
],
"properties": {
"lang": {
"enum": [
"Java"
]
},
"trainer": {
"type": "string"
}
}
},
"JavaScript": {
"required": [
"enrolled",
"available"
],
"properties": {
"lang": {
"enum": [
"JavaScript"
]
},
"enrolled": {
"type": "string"
},
"available": {
"type": "string"
}
}
}
}
}
I think that the "array" definition is not correct. The objects that can be added in the array must be refereed in the "items", after you define the type of the items. Something like this:
"languages": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"anyOf": [
{"$ref": "#/definitions/Java"},
{"$ref": "#/definitions/JavaScript"}
]
}
}
I have fixed myself
What I did: I have placed the json object blocks under items section of array.

Json schema validation for property that can only be set once on an object inside an array

Is it possible to validate the json data below, so that "info" can only be filled in when "name" is "a" otherwise it must be empty or null?
[
{
"name": "a",
"info": "this is mandatory"
},
{
"name": "b",
"info": "validation must fail"
}
]
the JSONSchema
{
"title": "Array of things",
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string",
"enum": [
"a",
"b"
]
},
"info": {
"type": "string"
}
}
}
}
The json in an online editor
try this:
{
"title": "Array of things",
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string",
"enum": ["a", "b"]
},
"info" : {
"type": ["string", "null"]
}
},
"required": ["name"],
"oneOf": [
{
"properties": {
"name": {"enum": ["a"] }
},
"required": ["info"]
},
{
"properties": {
"name": {"enum": ["b"] },
"info": {"enum": [null]}
}
}
]
}
}

allow one of all based on the same base type

I have the following json schema:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"description": "schema validating people and vehicles",
"definitions": {
"base": {
"properties": {
"age": {
"type": "integer"
}
},
"required": [
"age"
]
},
"person": {
"$ref": "#/definitions/base",
"additionalProperties": false,
"properties": {
"firstName": {
"type": "string"
},
"lastName": {
"type": "string"
},
"sport": {
"type": "string"
}
},
"required": [
"firstName"
]
},
"vehicle": {
"$ref": "#/definitions/base",
"additionalProperties": false,
"properties": {
"vehicle": {
"type": "string"
},
"price": {
"type": "integer"
}
}
}
},
"type": "object",
"oneOf": [
{
"$ref": "#/definitions/person",
},
{
"$ref": "#/definitions/vehicle",
}
]
}
And i want it to validate against
{"firstName":"John", "lastName":"Doe", "sport": "football", "age": 15}
and the following
{"type": "car", "price": 100, "age": 3}
I get the following error JSON is valid against more than one schema from 'oneOf'. Valid schema indexes: 0, 1..
Why is it valid against more then one? (firstName is only defined in person and type is only defined in vehicle.)
JSON Schema doesn't support inheritance.
See:
https://github.com/json-schema-org/json-schema-spec/issues/348
https://spacetelescope.github.io/understanding-json-schema/reference/combining.html
JSon schema and Inheritance

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