[ { "description": "$recursiveRef without $recursiveAnchor works like $ref", "schema": { "properties": { "foo": { "$recursiveRef": "#" } }, "additionalProperties": false }, "tests": [ { "description": "match", "data": {"foo": false}, "valid": true }, { "description": "recursive match", "data": { "foo": { "foo": false } }, "valid": true }, { "description": "mismatch", "data": { "bar": false }, "valid": false }, { "description": "recursive mismatch", "data": { "foo": { "bar": false } }, "valid": false } ] }, { "description": "$recursiveRef without using nesting", "schema": { "$id": "http://localhost:4242/recursiveRef2/schema.json", "$defs": { "myobject": { "$id": "myobject.json", "$recursiveAnchor": true, "anyOf": [ { "type": "string" }, { "type": "object", "additionalProperties": { "$recursiveRef": "#" } } ] } }, "anyOf": [ { "type": "integer" }, { "$ref": "#/$defs/myobject" } ] }, "tests": [ { "description": "integer matches at the outer level", "data": 1, "valid": true }, { "description": "single level match", "data": { "foo": "hi" }, "valid": true }, { "description": "integer does not match as a property value", "data": { "foo": 1 }, "valid": false }, { "description": "two levels, properties match with inner definition", "data": { "foo": { "bar": "hi" } }, "valid": true }, { "description": "two levels, no match", "data": { "foo": { "bar": 1 } }, "valid": false } ] }, { "description": "$recursiveRef with nesting", "schema": { "$id": "http://localhost:4242/recursiveRef3/schema.json", "$recursiveAnchor": true, "$defs": { "myobject": { "$id": "myobject.json", "$recursiveAnchor": true, "anyOf": [ { "type": "string" }, { "type": "object", "additionalProperties": { "$recursiveRef": "#" } } ] } }, "anyOf": [ { "type": "integer" }, { "$ref": "#/$defs/myobject" } ] }, "tests": [ { "description": "integer matches at the outer level", "data": 1, "valid": true }, { "description": "single level match", "data": { "foo": "hi" }, "valid": true }, { "description": "integer now matches as a property value", "data": { "foo": 1 }, "valid": true }, { "description": "two levels, properties match with inner definition", "data": { "foo": { "bar": "hi" } }, "valid": true }, { "description": "two levels, properties match with $recursiveRef", "data": { "foo": { "bar": 1 } }, "valid": true } ] }, { "description": "$recursiveRef with $recursiveAnchor: false works like $ref", "schema": { "$id": "http://localhost:4242/recursiveRef4/schema.json", "$recursiveAnchor": false, "$defs": { "myobject": { "$id": "myobject.json", "$recursiveAnchor": false, "anyOf": [ { "type": "string" }, { "type": "object", "additionalProperties": { "$recursiveRef": "#" } } ] } }, "anyOf": [ { "type": "integer" }, { "$ref": "#/$defs/myobject" } ] }, "tests": [ { "description": "integer matches at the outer level", "data": 1, "valid": true }, { "description": "single level match", "data": { "foo": "hi" }, "valid": true }, { "description": "integer does not match as a property value", "data": { "foo": 1 }, "valid": false }, { "description": "two levels, properties match with inner definition", "data": { "foo": { "bar": "hi" } }, "valid": true }, { "description": "two levels, integer does not match as a property value", "data": { "foo": { "bar": 1 } }, "valid": false } ] }, { "description": "$recursiveRef with no $recursiveAnchor works like $ref", "schema": { "$id": "http://localhost:4242/recursiveRef5/schema.json", "$defs": { "myobject": { "$id": "myobject.json", "$recursiveAnchor": false, "anyOf": [ { "type": "string" }, { "type": "object", "additionalProperties": { "$recursiveRef": "#" } } ] } }, "anyOf": [ { "type": "integer" }, { "$ref": "#/$defs/myobject" } ] }, "tests": [ { "description": "integer matches at the outer level", "data": 1, "valid": true }, { "description": "single level match", "data": { "foo": "hi" }, "valid": true }, { "description": "integer does not match as a property value", "data": { "foo": 1 }, "valid": false }, { "description": "two levels, properties match with inner definition", "data": { "foo": { "bar": "hi" } }, "valid": true }, { "description": "two levels, integer does not match as a property value", "data": { "foo": { "bar": 1 } }, "valid": false } ] }, { "description": "$recursiveRef with no $recursiveAnchor in the initial target schema resource", "schema": { "$id": "http://localhost:4242/recursiveRef6/base.json", "$recursiveAnchor": true, "anyOf": [ { "type": "boolean" }, { "type": "object", "additionalProperties": { "$id": "http://localhost:4242/recursiveRef6/inner.json", "$comment": "there is no $recursiveAnchor: true here, so we do NOT recurse to the base", "anyOf": [ { "type": "integer" }, { "type": "object", "additionalProperties": { "$recursiveRef": "#" } } ] } } ] }, "tests": [ { "description": "leaf node does not match; no recursion", "data": { "foo": true }, "valid": false }, { "description": "leaf node matches: recursion uses the inner schema", "data": { "foo": { "bar": 1 } }, "valid": true }, { "description": "leaf node does not match: recursion uses the inner schema", "data": { "foo": { "bar": true } }, "valid": false } ] }, { "description": "$recursiveRef with no $recursiveAnchor in the outer schema resource", "schema": { "$id": "http://localhost:4242/recursiveRef7/base.json", "anyOf": [ { "type": "boolean" }, { "type": "object", "additionalProperties": { "$id": "http://localhost:4242/recursiveRef7/inner.json", "$recursiveAnchor": true, "anyOf": [ { "type": "integer" }, { "type": "object", "additionalProperties": { "$recursiveRef": "#" } } ] } } ] }, "tests": [ { "description": "leaf node does not match; no recursion", "data": { "foo": true }, "valid": false }, { "description": "leaf node matches: recursion only uses inner schema", "data": { "foo": { "bar": 1 } }, "valid": true }, { "description": "leaf node does not match: recursion only uses inner schema", "data": { "foo": { "bar": true } }, "valid": false } ] }, { "description": "multiple dynamic paths to the $recursiveRef keyword", "schema": { "$id": "recursiveRef8_main.json", "$defs": { "inner": { "$id": "recursiveRef8_inner.json", "$recursiveAnchor": true, "title": "inner", "additionalProperties": { "$recursiveRef": "#" } } }, "if": { "propertyNames": { "pattern": "^[a-m]" } }, "then": { "title": "any type of node", "$id": "recursiveRef8_anyLeafNode.json", "$recursiveAnchor": true, "$ref": "recursiveRef8_main.json#/$defs/inner" }, "else": { "title": "integer node", "$id": "recursiveRef8_integerNode.json", "$recursiveAnchor": true, "type": [ "object", "integer" ], "$ref": "recursiveRef8_main.json#/$defs/inner" } }, "tests": [ { "description": "recurse to anyLeafNode - floats are allowed", "data": { "alpha": 1.1 }, "valid": true }, { "description": "recurse to integerNode - floats are not allowed", "data": { "november": 1.1 }, "valid": false } ] }, { "description": "dynamic $recursiveRef destination (not predictable at schema compile time)", "schema": { "$id": "main.json", "$defs": { "inner": { "$id": "inner.json", "$recursiveAnchor": true, "title": "inner", "additionalProperties": { "$recursiveRef": "#" } } }, "if": { "propertyNames": { "pattern": "^[a-m]" } }, "then": { "title": "any type of node", "$id": "anyLeafNode.json", "$recursiveAnchor": true, "$ref": "main.json#/$defs/inner" }, "else": { "title": "integer node", "$id": "integerNode.json", "$recursiveAnchor": true, "type": [ "object", "integer" ], "$ref": "main.json#/$defs/inner" } }, "tests": [ { "description": "numeric node", "data": { "alpha": 1.1 }, "valid": true }, { "description": "integer node", "data": { "november": 1.1 }, "valid": false } ] } ]