Json schema validation for object which may have two forms - json

I'm trying to figure out how to validate a JSON object which may have 2 forms.
for examples
when there is no data available, the JSON could be
{
"student": {}
}
when there is data available, the JSON could be
{
"student":{
"id":"someid",
"name":"some name",
"age":15
}
}
I wrote the JSON schema in this way, but it seems not working
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "http://json-schema.org/draft-07/schema#",
"title": "JSON schema validation",
"properties": {
"student": {
"type": "object",
"oneOf": [
{
"required": [],
"properties": {}
},
{
"required": [
"id",
"name",
"age"
],
"properties": {
"id": {
"$id": "#/properties/student/id",
"type": [
"string",
"null"
]
},
"name": {
"$id": "#/properties/student/name",
"type": [
"string",
"null"
]
},
"age": {
"$id": "#/properties/student/age",
"type": [
"number"
]
}
}
}
]
}
}
}
I was wondering is there a way to validate it. Thank you!

An empty properties object, and an empty required object, do nothing.
JSON Schema is constraints based, in that if you don't explicitly constrain what is allowed, then it is allowed by default.
You're close, but not quite. The const keyword can take any value, and is what you want in your first item of allOf.
You can test the following schema here: https://jsonschema.dev/s/Kz1C0
{
"$schema": "http://json-schema.org/draft-07/schema",
"$id": "https://example.com/myawesomeschema",
"title": "JSON schema validation",
"properties": {
"student": {
"type": "object",
"oneOf": [
{
"const": {}
},
{
"required": [
"id",
"name",
"age"
],
"properties": {
"id": {
"type": [
"string",
"null"
]
},
"name": {
"type": [
"string",
"null"
]
},
"age": {
"type": [
"number"
]
}
}
}
]
}
}
}

Related

JsonSchema - Only allow one item in an array field if another array field is defined

I have the following json and would like to only allow "leads" to contain only a single "id" item if there is a "tokens" array present (with at least one item).
JSON
{
"input": {
"leads": [
{
"id": 795333333760
}
],
"tokens": [
{
"name": "tem_x",
"value": "Renew_all"
},
{
"duration": "90",
"eligibility": "eligible"
}
]
}
I have the following schema, that indicates "tokens" can have more than one item if present and that "leads" is required.
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"input": {
"type": "object",
"properties": {
"leads": {
"type": "array",
"items": [
{
"type": "object",
"properties": {
"id": {
"type": "integer"
}
},
"required": [
"id"
]
}
]
},
"tokens": {
"type": "array",
"minItems": 1
}
},
"required": [
"leads",
]
}
},
"required": [
"input"
]
}
Is there a way to ensure that only one item in "leads" can be allowed if "tokens" is present (as it is not defined as a required field). If "tokens" is not defined, then I would like to allow the "leads" array to have more than one item.
I played around with if-then but wasn't able to get it working right. Any help is appreciated.
Thank you.
This is the kind of thing the dependencies keyword is for. It can be done with if/then or implication as well, but dependencies removes all the extra boilerplate needed for those patterns. The following says, if the "tokens" property is defined, then the "leads" property must have at most 1 item. This would go inside your "input" schema.
"dependencies": {
"tokens": {
"properties": {
"leads": { "maxItems": 1 }
}
}
}
Edit: dependencies works in draft-04 thru draft-07. In draft 2019-09 and up, you can use dependentSchemas instead.
try to use like this:
{
"properties": {
"tokens": {},
"leads": {}
},
"anyOf": [{
"required" : ["tokens"]
}, {
"required" : ["leads"]
}]
}
so schema looks like this:
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"input": {
"type": "object",
"properties": {
"leads": {
"type": "array",
"items": [
{
"type": "object",
"properties": {
"id": {
"type": "integer"
}
},
"required": [
"id"
]
}
]
},
"tokens": {
"type": "array",
"minItems": 1
}
},
"anyOf": [{
"required" : ["tokens"]
}, {
"required" : ["leads"]
}]
}
},
"required": [
"input"
]
}

How to use logic if else in json schema to validate array item?

i have json like this
{ "user" : ["foo", "bar"] }
i want use if else here
if there "foo" in array user then field admin is required
I've tried it like this
{
"$schema": "http://json-schema.org/draft-07/schema",
"title": "JSON Schema for role",
"type": "object",
"properties": {
"user": {
"type": ["array"],
"items" : {
"type" : "string",
"enum" : [
"foo",
"bar"
]
}
},
"admin" : {"type" : "string"},
"if": {
"properties": {
"user": { "const": "foo" }
},
"required": ["user"]
},
"then": { "required": ["admin"] }
},"additionalProperties": false}
but not work
const is applicable to single values, but you want to check the contense of an array.
You want contains. contains applies it's value (which is a subschema) to each item in the array, to check at least one of the items is what is expected.
You also needed to have your if and then keywords be part of a schema object. You had them as part of the properties object.
{
"$schema": "http://json-schema.org/draft-07/schema",
"title": "JSON Schema for role",
"type": "object",
"properties": {
"user": {
"type": [
"array"
],
"items": {
"type": "string",
"enum": [
"foo",
"bar"
]
}
},
"admin": {
"type": "string"
}
},
"required": [
"user"
],
"if": {
"properties": {
"user": {
"contains": {
"type": "string",
"const": "foo"
}
}
}
},
"then": {
"required": [
"admin"
]
},
"additionalProperties": false
}
See it working: https://jsonschema.dev/s/RaxvK

JSON Schema for child objects with different set of keys

I have JSON data of which is an array of data like
[
{
"type": "background_color",
"data": {
"backgroundColor": "F9192D"
}
},
{
"type": "banner_images",
"data": {
"images": [
{
"url": "https://example.com/abc.jpg",
"id": 3085
},
{
"url": "https://example.com/zyx.jpg",
"id": 3086
}
]
}
},
{
"type": "description_box",
"data": {
"text": "Hello 56787"
}
}
]
The data is an array of object which has two keys type and data. The type and keys of the data will be defined by the type of data it has.
Like for background_color type, the data should have backgroundColor property, while for banner_images, data should have images which is an array of other properties.
Till now, What I have done is
{
"definitions": {},
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "array",
"title": "category schema",
"description": "Used to validate data of category",
"examples": [],
"required": [],
"items": {
"type": "object",
"required": [
"type",
"data"
],
"properties": {
"type": {
"type": "string",
"enum": ["background_color", "banner_images", "description_box"]
},
"data": {
"type": "object" // How to define data property here for each use case
}
}
}
}
I'm not getting how to define the data property for each use case?
You can use if/then/else blocks to define conditional constraints.
The values of if and then are schemas. If the if schema is valid, then the then schema is applied, otherwise, the allOf subschema (allOf[0] in this example) would pass validation.
There are a few different ways to do this, but this is clean when you don't have any additional or special requirements. Please come back if you do =]
In this example, I've added banner_images...
You can test it working here.
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "array",
"title": "category schema",
"description": "Used to validate data of category",
"items": {
"type": "object",
"required": [
"type",
"data"
],
"properties": {
"type": {
"type": "string",
"enum": [
"background_color",
"banner_images",
"description_box"
]
},
"data": {
"type": "object"
}
},
"allOf": [
{
"if": {
"properties": {
"type": {
"const": "banner_images"
}
}
},
"then": {
"properties": {
"data": {
"required": [
"images"
],
"properties": {
"images": {
"type": "array"
}
}
}
}
}
}
]
}
}
For reference, here's the part of the JSON Schema draft-7 spec document that details the behaviour: https://datatracker.ietf.org/doc/html/draft-handrews-json-schema-validation-01#section-6.6

Array of objects or strings in JSON Schema

struggling to find a definitive answer to this.
I'd writing some JSON schema validation, and wish to validate against the incoming payload being either an array of strings (that match a pattern) or an array of objects.
For instance...
{
"src" : [
{
"serviceName" : "svc1",
"filename" : "ABC000000001234567.tar"
},
{
"serviceName" : "svc2",
"filename" : "DEF000000001234567.tar"
}
]
}
..or...
{
"src" : [
"file://svc1/ABC000000001234567.tar",
"file://svc2/DEF000000001234567.tar"
]
}
I have this at the moment, but it isn't working...
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"title": "My schema",
"additionalProperties": false,
"properties": {
"src": {
"type": "array",
"additionalItems": false,
"items": {
"oneOf": [
{
"$ref": "#/definitions/svcUrl"
},
{
"$ref": "#/definitions/svcObj"
}
]
}
}
},
"definitions": {
"svcUrl": {
"type": "string",
"pattern": "^file\\:\\/\\/",
"required": []
},
"svcObj": {
"type": "object",
"properties": {
"serviceName": {
"type": "string"
},
"filename": {
"type": "string"
}
},
"required": [
"RequiredProperty",
"filename",
"serviceName"
]
}
}
}
Can anyone help shed some light on this for me please?

How to use definitions in JSON schema (draft-04)

The rest service response I am working with is similar to following example, I have only included 3 fields here but there are many more:
{
"results": [
{
"type": "Person",
"name": "Mr Bean",
"dateOfBirth": "14 Dec 1981"
},
{
"type": "Company",
"name": "Pi",
"tradingName": "Pi Engineering Limited"
}
]
}
I want to write a JSON schema file for above (draft-04) which will explicitly specify that:
if type == Person then list of required properties is ["type", "name", "dateOfBirth", etc]
OR
if type == "Company" then list of required properties is ["type", "name", "tradingName", etc]
However am unable to find any documentation or example of how to do it.
Currently my JSON schema looks like following:
{
"$schema": "http://json-schema.org/draft-04/schema",
"type": "object",
"required": ["results" ],
"properties": {
"results": {
"type": "array",
"items": {
"type": "object",
"required": ["type", "name"],
"properties": {
"type": { "type": "string" },
"name": { "type": "string" },
"dateOfBirth": { "type": "string" },
"tradingName": { "type": "string" }
}
}
}
}
}
Any pointers/examples of how I should handle this.
I think the recommended approach is the one shown in Json-Schema web, Example2. You need to use an enum to select schemas "by value". In your case it would be something like:
{
"type": "object",
"required": [ "results" ],
"properties": {
"results": {
"type": "array",
"items": {
"oneOf": [
{ "$ref": "#/definitions/person" },
{ "$ref": "#/definitions/company" }
]
}
}
},
"definitions": {
"person": {
"properties": {
"type": { "enum": [ "person" ] },
"name": {"type": "string" },
"dateOfBirth": {"type":"string"}
},
"required": [ "type", "name", "dateOfBirth" ],
"additionalProperties": false
},
"company": {
"properties": {
"type": { "enum": [ "company" ] },
. . .
}
}
}
}
Sorry,
I don't get the point. The question is about the 'dependencies' keyword which is part of the last JSON Schema specification, right?
I do not find 'dependencies' in the accepted answer (?)
It is briefly explained in the last draft.
But http://usingjsonschema.com explained both property and definition dependencies in the book:
http://usingjsonschema.com/assets/UsingJsonSchema_20140814.pdf
start at page 29 (see, explained at page 30)
"dependencies": {
"shipTo":["shipAddress"],
"loyaltyId":["loyaltyBonus"]
}