JSONSchema local self-reference (recursion) - jsonschema

How can I reference a schema (B in this case) from itself no matter where it is nested?
I would like to be able to validate against schema A and against schema B. E.g.
from jsonschema import validate
validate(a, A)
validate(b, B)
Why? For unit tests and for speed improvements (if one of the B's fails I don't need to validate A).
Schema A references schema B and B references itself (see examples below).
I have tried the following:
a) Using definitions in A works only if validating against A. Validating B fails with jsonschema.exceptions.RefResolutionError: Unresolvable JSON pointer: 'definitions/b'. Which makes sense because the definition only exists on A.
from jsonschema import validate
B = {
"anyOf": [
{
"type": "object"
},
{
"type": "array",
"items": {"$ref": "#/definitions/b"}
}
]
}
A = {
"definitions": {
"b": B
},
"type": "array",
"items": {"$ref": "#/definitions/b"}
}
validate([], A)
validate([], B) # RefResolutionError
b) Using "$id": "http://example.org/B" in B and reference itself with: {"$ref": "http://example.org/B"} makes an actual (unnecessary http request) to a URL that does not exist. There is no need to make that request as the information is present in the document. Attempts using a non-url such as just #B fails with jsonschema.exceptions.RefResolutionError: unknown url type.
from jsonschema import validate
B = {
"$id": "http://example.org/schema/B",
"anyOf": [
{
"type": "object"
},
{
"type": "array",
"items": {"$ref": "http://example.org/schema/B"}
}
]
}
A = {
"type": "array",
"items": {"$ref": "http://example.org/schema/B"}
}
validate([{}], A) # RefResolutionError: HTTP Error 404: Not Found
validate([{}], B) # RefResolutionError: HTTP Error 404: Not Found

I had a problem kinda like this. I found upgrading my jsonschema module from somewhere in version 3 to jsonschema >= 4.3.2 fixed it immediately so may simply be a bug.
pip install --upgrade jsonschema

Related

Using $vars within json schema $ref is undefined

While following the documentation for using variables in json schema I noticed the following example fails. It looks like the number-type doesn't get stored as a variable and cannot be read.
{
"$id": "http://example.com/number#",
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": ["natural", "integer"]
},
"value": {
"$ref": "#/definitions/{+number-type}",
"$vars": {
"number-type": {"$ref": "1/type"}
}
}
},
"required": ["type", "value"],
"definitions": {
"natural": {
"type": "integer",
"minimum": 0
},
"integer": {
"type": "integer"
}
}
}
results in
Could not find a definition for #/definitions/{+number-type}
tl;dr $vars is not a JSON Schema keyword. It is an implementation specific extension.
The documentation you link to is not JSON Schema. It is documentation for a specific library which adds a preprocessing step to its JSON Schema processing model.
As such, this would only ever work when using that library, and would not create an interoperable or reuseable JSON Schema, if that's a consideration.
If you are using that library specifically, it sounds like a bug, and you should file an Issue in the appropriate repo. As you haven't provided any code, I can't tell what implementation you are using, so I can't be sure on that.

jsonschema dependentSchema not validating

I am trying to learn json schema, but something isn't working out for me.
I'm trying to run the example from http://json-schema.org/understanding-json-schema/reference/conditionals.html#id4 for dependentSchemas, but it just doesn't validate.
I'm using this schema:
check_schema = {"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"name": { "type": "string" },
"credit_card": { "type": "number" }
},
"required": ["name"],
"dependentSchemas": {
"credit_card": {
"properties": {
"billing_address": { "type": "string" }
},
"required": ["billing_address"]
}
}
}
and this json, that should raise an error since it is missing the key billing_address:
check_dict={
"name": "John Doe",
"credit_card": 5555555555555555
}
but when I use jsonschema.validate(dic_check, schema_check) (with python, jsonschema package version 4.2.1), the validation passes with no issues.
What am I doing wrong here?
If you are using an implementation that doesn't support at least draft2019-09 of the specification, dependentSchemas won't be recognized as a keyword. In earlier versions (draft7 and before), that keyword was known as dependencies, with the same syntax (actually, dependencies was split into two, dependentSchemas and dependentRequired).
The details are described on the page you linked, https://json-schema.org/understanding-json-schema/reference/conditionals.html#dependentschemas.
If you still believe that what you have should work, I suggest you open a bug report on the implementation's issue queue.

Extend $ref object properties

I am using JSON schema to build a form and I have an object in "definitions" which I am referencing using $ref in two different places on the schema. At one of the instances I need to have one more property added to the referenced object, how can I achieve this?
{
"definitions": {
"settingsProperties": {
"$id": "#/definitions/settingsProperties",
"type": "object",
"properties": {
"thickness": {
"$id": "#/properties/defaultLayerSettings/thickness",
"type": "number",
"title": "Thickness:",
}
}
}
},
"properties": {
"layerSettings": {
"$id": "#/properties/layerSettings",
"type": "array",
"title": "Dynamic Layer Settings:",
"items": {
"title": "Dynamic Settings",
"type": "object",
"$ref": "#/definitions/settingsProperties", PLUS startLayer PROPERTY!!!!!!!!!!!!!!
"required": [
"startLayer"
]
}
}
}
Just add "properties": { "startLayer": { ... } } underneath the required keyword.
Note that if you are using any specification version earlier than draft 2019-09 (the current latest version), you will have to nest the $ref keyword inside an allOf. Additionally, the use of fragments (strings that include #) are not permitted in the $id keyword, although some outdated tools are generating schemas with this structure.

How to use definitions from external files in JSON Schema?

I'm trying to import the definitions from another json schema using $ref but getting the following error:
can't resolve reference ../base/definitions.schema.json#/definitions/datetime from id #
{
"$schema": "http://json-schema.org/draft-06/schema#",
"definitions": {
"datetime": {
"type": "string"
},
"name": {
"type": "string"
},
}
}
{
"$schema": "http://json-schema.org/draft-06/schema#",
"properties": {
"active": {"type": "boolean"},
"created_at": { "$ref": "../base/definitions.schema.json#/definitions/datetime" },
"name": { "$ref": "../base/base/definitions.schema.json#/definitions/name" },
"updated_at": { "$ref": "../base/definitions.schema.json#/definitions/datetime" }
},
"required": ["name"],
"type": "object"
}
Directory structure:
api
-- base
-- definitions.schema.json
-- country
-- country.schema.json
I have tried several combinations by using an absolute path, a file url and several other combinations of the path. Not sure what's going on.
Schema validator: ajv#5.1.1
You need to add schemas using "addSchema" method. $ref is resolved relative to "id" attribute ("$id" in draft-06), ajv doesn't (and can't) use file paths.
EDIT: added $ref section to docs.

Dredd (gavel) : Begin a Json Schema with an array (bug ?)

I am using Markdown for Generate documentation (aglio), generate mocks (api-mock) and check the integrity constraints (dredd).
With Dredd, no problem for check an object, no problem for PUT or POST, but I have a problem with lists.
My lists are arrays, but when I write this schema :
{
"title": "Videos List",
"type": "array",
"items": {
"type":"object",
"required":false,
"properties": {
"id": {
"type": "string",
"required": true
}
},
"required": true
}
}
I get same error all the time: body: JSON schema is not valid! invalid type: object (expected [object Object]/array) at path "/items"
I've tried, again and again, 3 hours, but I failed.
Please help!
PS : sorry for my English, I'm french.
Yes, your data is correct again that schema.
It might be a specific problem of the validator your are using (you did not mention which). You can try to enclose your data with {}. I guess it is expecting allways a JSON like this:
{
[
{
"id": "ninon-retrouve-rudy",
"title": "Ninon retrouve Rudy edited"
},
{
"id": "ninon-retrouve-rudy-1",
"title": "Ninon retrouve Rudy"
}
]
}
Be aware also that your are using Draft03 of Json-schema. I suggest you to use Draft04 (your validator might be obsolete).