How do I reference properties in Json Schema? - json

I want to reference each property of the json object in a different file
This is what I'd like to do (but the validations are not working for me):
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties":
{
"id": { "$ref": "type/common.json#def_id" },
"title": { "$ref": "type/book.json#def_title" }
}
}
...
# type/common.json
{
"def_id":{
"id": {
"type": "string",
"format": "uuid",
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
}
}
}
# type/book.json
{
"def_title":{
"title": {
"anyOf": [
{
"type": "null"
},
{
"type": "string"
}
]
}
}
}
If you could help me I would be very grateful

I was referencing it wrong, it's work
{
"id": { "$ref": "type/common.json#/def_id/id" },
"title": { "$ref": "type/book.json#/def_title/title" }
}
this works for me

Related

Why is $ref valid under the JSON schema?

I have this schema:
{
"$schema": "http://json-schema.org/draft-07/schema",
"definitions": {
"person": {
"properties": {
"name": { "type": "string" }
}
},
"employee": {
"$ref": "#/definitions/person",
"properties": {
"salary": { "type": "number" }
}
}
},
"properties": {
"Entry": {
"$ref": "#/definitions/employee"
},
},
}
And surprisingly, the following JSON is valid under the schema:
{
"Entry": {
"name": "John",
"salary": "1234"
}
}
Can anyone explain how $ref works here? Why is this JSON valid?
-- EDIT --
I found that if I change
"$schema": "http://json-schema.org/draft-07/schema"
to
"$schema": "http://json-schema.org/draft-05/schema"
it will work as expected, but only "draft-05" works; others like "draft-04" "draft-06" are not working.
In JSON Schema versions up to and including draft 7, when the $ref keyword is adjacent to any other keyword, the other keywords are ignored.
You can work around this by enclosing the $ref in an allOf:
...
"employee": {
"allOf": [ { "$ref": "#/definitions/person" } ],
"properties": {
"salary": { "type": "number" }
}
}
},
...

Add pattern validation in json schema when property is present

Below is my schema definition and I would like to add pattern that depends on environment propertyName (env1, env2 or env3). Each env should have different pattern. For instance when env1 is present then url will have a different pattern than when env2 is present etc.
{
"environments": {
"env1": {
"defaultAccess": {
"url": [
"something-staging"
]
}
}
}
}
My current schema definition for that example
{
"$schema": "https://json-schema.org/draft-07/schema#",
"definitions": {
"envType": {
"type": "object",
"properties": {
"defaultAccess": {
"type": "object",
"properties": {
"url": {
"type": "string",
"pattern": "^[a-zA-Z0-9- \/]*$"
}
},
"required": [
"url"
]
}
}
},
"environmentTypes": {
"type": "object",
"properties": {
"env1": {
"$ref": "#/definitions/envType"
},
"env2": {
"$ref": "#/definitions/envType"
},
"env3": {
"$ref": "#/definitions/envType"
}
}
},
"type": "object",
"properties": {
"environments": {
"$ref": "#/definitions/environmentTypes"
}
}
}
}
In my head I have something like this but do not know how to apply it to the schema properly.
{
"if": {
"properties": {
"environments": {
"env1" : {}
}
}
},
"then":{
"properties": {
"environments-env1-defaultAccess-url" : { "pattern": "^((?!-env2).)*$" }
}
}
}
etc..
If understand correctly what you're trying to do, you shouldn't need conditionals for this kind of thing.
You have an error in your schema that might be tripping you up. You have your main schema inside the definitions keyword. If you run this through a validator, you should get an error saying that the value a /definitions/type must be an object.
Aside from that, schema composition using allOf should do the trick. Below, I've shown an example at /definitions/env1Type.
It looks like you were hoping for a less verbose way to specify a schema deep in an object structure (""). Unfortunately, there's no way around having to chain the properties keyword all the way down like I've demonstrated at /definitions/env1Type.
{
"$schema": "https://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"environments": { "$ref": "#/definitions/environmentTypes" }
},
"definitions": {
"environmentTypes": {
"type": "object",
"properties": {
"env1": { "$ref": "#/definitions/env1Type" },
"env2": { "$ref": "#/definitions/env2Type" },
"env3": { "$ref": "#/definitions/env3Type" }
}
},
"envType": { ... },
"env1Type": {
"allOf": [{ "$ref": "#/definitions/envType" }],
"properties": {
"defaultAccess": {
"properties": {
"url": { "pattern": "^((?!-env1).)*$" }
}
}
}
},
"env2Type": { ... },
"env3Type": { ... }
}
}

Json schema not validating/working with sub schema

I have json shown below. I want to get it work against a list of zoo which will must have zoo_unique_code. But can have animal or bird or both or none of them. But i want to validate it with sub schema if it have animal or bird e.g bird/animal_id. It seems subschema is not working.
{
"type": "object",
"$schema": "http://json-schema.org/draft-04/schema#",
"definitions": {
"animal_id": {
"type": "string",
"maxLength": 24
},
"bird_id": {
"type": "string",
"maxLength": 50
},
"zoo_bird_and_animal": {
"type": "object",
"anyOf": [{
"properties": {
"zoo_bird": {
"type": "object",
"required": [
"zoo_bird_id"
],
"properties": {
"zoo_bird_id": {
"$ref": "#/definitions/bird_id"
}
}
}
}
}, {
"properties": {
"zoo_animal": {
"type": "object",
"required": [
"zoo_animal_id"
],
"properties": {
"zoo_animal_id": {
"$ref": "#/definitions/animal_id"
}
}
}
}
}
]
}
},
"properties": {
"zoo_list": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": [
"zoo_unique_code"
],
"minProperties": 1,
"properties": {
"zoo_unique_code": {
"type": "string",
"enum": [
"NEWYORKZOO",
"PARISZOO"
]
}
},
"$ref": "#/definitions/zoo_bird_and_animal"
}
}
}
}
And testing it with
{
"zoo_list": [
{
"zoo_unique_code": "NEWYORKCODE",
"zoo_bird": {
"zoo_bird_id": "newid"
}
}
]
}
Any suggestion will be appreciated.
As far as i can interpret your schema, it seems you want to use a combining schema at the end, rather then having the ref in the same items part.
With this allOf the schema needs to be a valid object like defined in items and like the ref in the definitions
Also the other error comes from using anyOf instead of allOf.
With anyOf, it needs to be valid against either the first or the second of the schemas, as both validate against a object, even when the first is invalid, the second is valid, so everything is valid. This could also be changed with additionalProperties, but then it does not work the way you nested it.
anyOf: As long as a value validates against either of these schemas, it is considered valid against the entire combined schema.
- combining-schemas
You would also want to use allOf here, so it must validate against all, or rewrite this condition to not use an object here.
With that anyOf to allOf modification, your given data now also validates the bird_id:
And i think you are not using draft-04 here, looks like draft-7.
{
"type": "object",
"$schema": "http://json-schema.org/draft-04/schema#",
"definitions": {
"animal_id": {
"type": "string",
"maxLength": 24
},
"bird_id": {
"type": "string",
"maxLength": 50
},
"zoo_bird_and_animal": {
"type": "object",
"allOf": [
{
"properties": {
"zoo_bird": {
"type": "object",
"required": [
"zoo_bird_id"
],
"properties": {
"zoo_bird_id": {
"$ref": "#/definitions/bird_id"
}
}
}
}
},
{
"properties": {
"zoo_animal": {
"type": "object",
"required": [
"zoo_animal_id"
],
"properties": {
"zoo_animal_id": {
"$ref": "#/definitions/animal_id"
}
}
}
}
}
]
}
},
"properties": {
"zoo_list": {
"type": "array",
"minItems": 1,
"items": {
"allOf": [
{
"type": "object",
"required": [
"zoo_unique_code"
],
"minProperties": 1,
"properties": {
"zoo_unique_code": {
"type": "string",
"enum": [
"NEWYORKZOO",
"PARISZOO"
]
}
}
},
{
"$ref": "#/definitions/zoo_bird_and_animal"
}
]
}
}
}
}
Invalid data, see: invalid:
{
"zoo_list": [
{
"zoo_unique_code": "NEWYORKCODE",
"zoo_bird": {
"zoo_bird_id": "newidnewidnewidnewidnewidnewidnewnewidnewidnewidnewidnewidnewidnew"
}
}
]
}
Valid data, see valid:
{
"zoo_list": [
{
"zoo_unique_code": "NEWYORKZOO",
"zoo_bird": {
"zoo_bird_id": "newid"
}
}
]
}

JSON schema "switch" not working

I'm trying to use the switch attribute of JSON schema v5 using the https://github.com/epoberezkin/ajv library.
I have the following schema but it's not working.
{
"type": "array",
"id": "http://localhost/drinks.json",
"items": {
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"switch": [
{
"if": {
"properties": {
"type": {
"enum": ["coffee", "tea"]
}
}
},
"then": {
"$ref": "http://localhost/caffeinated.json"
}
},
{
"then": {
"$ref": "http://localhost/decaf.json"
}
}
]
}
}
}
}
}
To be clear, the $refs work just fine without the switch statement. For example, this gets validated correctly:
{
"type": "array",
"id": "http://localhost/drinks.json",
"items": {
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"oneOf": [
{
"$ref": "http://localhost/caffeinated.json"
},
{
"$ref": "http://localhost/decaf.json"
}
]
}
}
}
}
}
But the first schema doesn't work, and by "doesn't work" I mean it doesn't even trigger valid/invalid. Did I do something wrong?

Ensure one property is not empty in JSON schema

For the given schema below, is it possible to ensure that at least one property contains a value (ie, minLength is 1):
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"fundRaiseId": {
"type": "string"
},
"productTypeId": {
"type": "string"
},
"businessLineId": {
"type": "string"
}
}
}
So this would pass validation:
{
"fundRaiseId": "x"
}
And this would fail as no values are present:
{
"fundRaiseId": "",
"productTypeId": "",
"businessLineId": ""
}
I would try something like
{
"allOf": [{
"type": "object",
"properties": {
"fundRaiseId": {
"type": "string"
},
"productTypeId": {
"type": "string"
},
"businessLineId": {
"type": "string"
}
}
}, {
"anyOf": [{
"properties": {
"fundRaiseId": {
"$ref": "#/definitions/nonEmptyString"
}
}
}, {
"properties": {
"productTypeId": {
"$ref": "#/definitions/nonEmptyString"
}
}
}, {
"properties": {
"businessLineId": {
"$ref": "#/definitions/nonEmptyString"
}
}
}]
}],
"definitions": {
"nonEmptyString": {
"type": "string",
"minLength": 1
}
}
}
Explanation: the JSON to be validated should conform to 2 root-level schemas, one is your original definition (3 string properties). The other one contains 3 additional sub-schemas, each defining one of your original properties as non-empty string. These are wrapped in an "anyOf" schema, so at least one of these should match, plus the original schema.
Is it a requirement that you allow the values to be empty? You can write a much cleaner schema if you requiring that all the strings are non-empty.
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"fundRaiseId": { "$ref": "#/definitions/non-empty-string" },
"productTypeId": { "$ref": "#/definitions/non-empty-string" },
"businessLineId": { "$ref": "#/definitions/non-empty-string" }
},
"anyOf": [
{ "required": ["fundRaiseId"] },
{ "required": ["productTypeId"] },
{ "required": ["businessLineId"] }
],
"definitions": {
"non-empty-string": {
"type": "string",
"minLength": 1
},
}
}