Json Schema Conditional if/Then not working - json

I'm new to Json Schema validation. I think the validation should fail, but it passes. Not sure why the If/then is not forcing the required field. I believe I formatted the If/Then correctly.
JSON:
{
"name": "Battery Wear",
"triggerAlert": {
"trigger": "When",
"timeSpan": 50,
"timeSpanMeasure": "Hours"
}
}
SCHEMA:
{
"$schema": "http://json-schema.org/draft-07/schema",
"type": "object",
"required": [
"name",
"triggerAlert"
],
"properties": {
"name": {
"type": "string"
},
"triggerAlert": {
"type": "object",
"required": ["trigger"],
"properties": {
"trigger": {
"type": "string",
"enum": ["Always","When"]
},
"numberOfEvents": {
"type": "integer"
},
"timeSpan": {
"type": "integer"
},
"timeSpanMeasure": {
"type": "string"
}
},
"if": { "properties": {"trigger": {"enum": ["When"]} } },
"then": {
"required": [
"numberOfEvents",
"timeSpan",
"timeSpanMeasure"
]
}
}
}
}

Depending on the implementation you are using, you may not have support for these conditionals. if/then/else were only added in specification draft 7.
The schema is correct; the expected error result is:
{
"errors" : [
{
"error" : "missing property: numberOfEvents",
"instanceLocation" : "/triggerAlert",
"keywordLocation" : "/properties/triggerAlert/then/required"
},
{
"error" : "subschema is not valid",
"instanceLocation" : "/triggerAlert",
"keywordLocation" : "/properties/triggerAlert/then"
},
{
"error" : "not all properties are valid",
"instanceLocation" : "",
"keywordLocation" : "/properties"
}
],
"valid" : false
}

Related

How to validate the json against a complex json schema which has multi level of references

I have a json schema as follows
{
"$id": "https://example.com/arrays.schema.json",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"description": "A representation of a person, company, organization, or place",
"type": "object",
"properties": {
"fruits": {
"type": "array",
"items": {
"type": "string"
}
},
"vegetables": {
"type": "array",
"items": { "$ref": "#/$defs/veggie" }
}
},
"required" : ["fruits", "vegetables"],
"$defs": {
"veggie": {
"type": "object",
"required": [ "veggieName", "veggieLike", "cropLocation"],
"properties": {
"veggieName": {
"type": "string",
},
"veggieLike": {
"type": "boolean",
},
"cropLocation" : {
"type" : "object",
"items" :{ "$ref" : "#/$defs/location"}
}
}
},
"location" : {
"type" : "object",
"required" : ["country", "state"],
"properties" : {
"country" : {
"type": "string"
},
"state" : {
"type": "string"
}
}
}
}
}
When I give data as follows I am expecting error that cropLocation doesnt have state and country prperty. but it validates as success against that schema. How to define schema with multilevel complex objects.
"fruits": [ "apple", "orange", "pear" ],
"vegetables": [
{
"veggieName" : "carrot",
"veggieLike": true,
"cropLocation" : {}
},
{
"veggieName": "broccoli",
"veggieLike": false,
"cropLocation" : {}
}
]
}
I tried variuos ways to restrucutre the json schema, but is not working
The error is here:
"items" :{ "$ref" : "#/$defs/location"}
"cropLocation" is an object, but items is a keyword that only applies to arrays. Simply remove the items keyword and make the $ref a sibling to "type": "object".

How to refactorice properties using json schema?

I'd like to reference and factor the following json schema in multiple files for a better handling regarding its properties. Files as "$ref": "book.json" and "$ref": "pencil.json" which each file has its own properties and validations (and of course, that it works "addProperties = false"), I have the following schema:
{
"additionalProperties": false,
"properties": {
"id": {
"type": "string"
},
"type": {
"type": "string",
"enum": ["Pencil", "Book"]
},
"title": {
"type": "string"
},
"content": {
"type": "string"
},
"domain": {
"type": "string"
},
"img_url": {
"type": "string"
},
"url": {
"type": "string"
}
},
"allOf": [
{
"if": {
"properties": {
"type": {
"enum": ["Book"]
}
}
},
"then": {
"required": [
"domain", "img_url", "url"
],
"not" : {
"anyOf" : [
{ "required" : ["content"] }
]
}
}
},
{
"if": {
"properties": {
"type": {
"enum": ["Pencil"]
}
}
},
"then": {
"required": [
"content"
],
"not" : {
"anyOf" : [
{ "required" : ["domain"] },
{ "required" : ["img_url"] },
{ "required" : ["url"] }
]
}
}
}
]
}
and I would like something like this:
# book.json
{
"properties": {
"content": {
"type": "string"
}
},
"if": {
"properties": {
"type": {
"enum": ["Book"]
}
}
},
"then": {
"required": [
"content"
],
"not" : {
"anyOf" : [
{ "required" : ["domain"] },
{ "required" : ["img_url"] },
{ "required" : ["url"] }
]
}
}
}
# pencil.json
{
"properties":{
"domain": {
"type": "string"
},
"img_url": {
"type": "string"
},
"url": {
"type": "string"
}
},
"if": {
"properties": {
"type": {
"enum": ["Pencil"]
}
}
},
"then": {
"required": [
"domain", "img_url", "url"
],
"not" : {
"anyOf" : [
{ "required" : ["content"] }
]
}
}
}
# properties.json
{
"additionalProperties": false,
"properties": {
"$ref": book.json,
"$ref": pencil.json
}
I would like to simplify it, whether a property is of the book or pencil type then it refers to the file where this file has its properties and validations.

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

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?

Json schema oneOf with additionalProperties draft-04

I am trying to make a schema for validating a policy language. Short:
a policy is associated with an assertion. This assertion can either be an operator (and, or, not) and contains a list of other assertions. An assertion can also be a primitive (leaf node).
I made an UML design to make things easier to understand:
UML diagram
{
"policy": {
"name": "test",
"expression": {
"operator": "all",
"value": [
{
"primitive": "encrypt",
"preference": 12345,
"usage": "required"
},
{
"primitive": "sign",
"preference": 12345,
"usage": "required"
}
],
"preference": 12345,
"usage": "required"
}
}
}
And here is the scheme I currenty made:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"minProperties": 1,
"additionalProperties": {
"$ref": "#/definitions/policy"
},
"definitions": {
"policy": {
"title": "Policy",
"type": "object",
"required": [
"name",
"expression"
],
"additionalProperties": false,
"properties": {
"name": {
"type": "string"
},
"expression": {
"$ref": "#/definitions/assertion"
}
}
},
"operator": {
"properties": {
"value": {
"type": "array",
"items": {
"$ref": "#/definitions/assertion"
}
},
"operator": {
"enum": [
"allOne",
"all"
]
}
}
},
"primitive": {
"properties": {
"primitive": {
"enum": [
"encrypt",
"sign"
]
}
}
},
"assertion": {
"type": "object",
"additionalProperties": false,
"oneOf": [
{
"$ref": "#/definitions/operator"
},
{
"$ref": "#/definitions/primitive"
}
],
"properties": {
"preference": {
"type": "integer",
"minimum": 0,
"exclusiveMinimum": true
},
"usage": {
"enum": [
"required",
"rejected",
"optional",
"observed",
"ignored"
]
}
}
}
}
}
With the use of "oneOf" I'm trying to either use the specification of an operator or a primitive. But I'm not sure this is the way to go because i received the following error:
"message" : "object instance has properties which are not allowed by the schema: [\"operator\",\"value\"]"
The error message complains about extra properties which are not defined (because of "additionalProperties": false). However, these are defined in the definitions...
The oneOf, anyOf, ... keywords cannot be used for referencing other definitions. They do work for required. The solution is to declare all properties and only require the properties that are needed in the context. My example would become the following:
"assertion": {
"type": "object",
"additionalProperties": false,
"oneOf": [
{
"required": [
"operator"
]
},
{
"required": [
"primitive"
]
}
],
"properties": {
"operator": {
"$ref": "#/definitions/operator"
},
"primitive": {
"$ref": "#/definitions/primitive"
},
"preference": {
"type": "integer",
"minimum": 0,
"exclusiveMinimum": true
},
"usage": {
"enum": [
"required",
"rejected",
"optional",
"observed",
"ignored"
]
}
}
}