Recursive schema extension

The following script implements the recursive schema extension example, described in the JSON Schema 2020-12 core specification.

import pprint

from jschon import create_catalog, JSON, JSONSchema

# create a catalog with support for JSON Schema version 2020-12
create_catalog('2020-12')

# define an extensible tree schema
tree_schema = JSONSchema({
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "$id": "https://example.com/tree",
    "$dynamicAnchor": "node",
    "type": "object",
    "properties": {
        "data": True,
        "children": {
            "type": "array",
            "items": {
                "$dynamicRef": "#node"
            }
        }
    }
})

# define a strict-tree schema, which guards against misspelled properties
strict_tree_schema = JSONSchema({
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "$id": "https://example.com/strict-tree",
    "$dynamicAnchor": "node",
    "$ref": "tree",
    "unevaluatedProperties": False
})

# declare a JSON instance with a misspelled field
tree_json = JSON({
    "children": [{"daat": 1}]
})

# evaluate the JSON instance with the tree schema
tree_result = tree_schema.evaluate(tree_json)

# evaluate the JSON instance with the strict-tree schema
strict_tree_result = strict_tree_schema.evaluate(tree_json)

# print output for the tree case
print('Tree schema verbose output:')
pprint.pp(tree_result.output('verbose'))

# print output for the strict-tree case
print('Strict tree schema verbose output:')
pprint.pp(strict_tree_result.output('verbose'))

The script produces the output shown below. The 'verbose' output format reflects the complete dynamic evaluation path through a schema and any referenced schemas.

Tree schema verbose output:
{'valid': True,
 'instanceLocation': '',
 'keywordLocation': '',
 'absoluteKeywordLocation': 'https://example.com/tree#',
 'annotations': [{'valid': True,
                  'instanceLocation': '',
                  'keywordLocation': '/type',
                  'absoluteKeywordLocation': 'https://example.com/tree#/type'},
                 {'valid': True,
                  'instanceLocation': '',
                  'keywordLocation': '/properties',
                  'absoluteKeywordLocation': 'https://example.com/tree#/properties',
                  'annotation': ['children'],
                  'annotations': [{'valid': True,
                                   'instanceLocation': '/children',
                                   'keywordLocation': '/properties/children',
                                   'absoluteKeywordLocation': 'https://example.com/tree#/properties/children',
                                   'annotations': [{'valid': True,
                                                    'instanceLocation': '/children',
                                                    'keywordLocation': '/properties/children/type',
                                                    'absoluteKeywordLocation': 'https://example.com/tree#/properties/children/type'},
                                                   {'valid': True,
                                                    'instanceLocation': '/children',
                                                    'keywordLocation': '/properties/children/items',
                                                    'absoluteKeywordLocation': 'https://example.com/tree#/properties/children/items',
                                                    'annotation': True,
                                                    'annotations': [{'valid': True,
                                                                     'instanceLocation': '/children/0',
                                                                     'keywordLocation': '/properties/children/items/$dynamicRef',
                                                                     'absoluteKeywordLocation': 'https://example.com/tree',
                                                                     'annotations': [{'valid': True,
                                                                                      'instanceLocation': '/children/0',
                                                                                      'keywordLocation': '/properties/children/items/$dynamicRef/type',
                                                                                      'absoluteKeywordLocation': 'https://example.com/tree#/type'},
                                                                                     {'valid': True,
                                                                                      'instanceLocation': '/children/0',
                                                                                      'keywordLocation': '/properties/children/items/$dynamicRef/properties',
                                                                                      'absoluteKeywordLocation': 'https://example.com/tree#/properties',
                                                                                      'annotation': []}]}]}]}]}]}
Strict tree schema verbose output:
{'valid': False,
 'instanceLocation': '',
 'keywordLocation': '',
 'absoluteKeywordLocation': 'https://example.com/strict-tree#',
 'errors': [{'valid': False,
             'instanceLocation': '',
             'keywordLocation': '/$ref',
             'absoluteKeywordLocation': 'https://example.com/tree',
             'errors': [{'valid': True,
                         'instanceLocation': '',
                         'keywordLocation': '/$ref/type',
                         'absoluteKeywordLocation': 'https://example.com/tree#/type'},
                        {'valid': False,
                         'instanceLocation': '',
                         'keywordLocation': '/$ref/properties',
                         'absoluteKeywordLocation': 'https://example.com/tree#/properties',
                         'error': "Properties ['children'] are invalid",
                         'errors': [{'valid': False,
                                     'instanceLocation': '/children',
                                     'keywordLocation': '/$ref/properties/children',
                                     'absoluteKeywordLocation': 'https://example.com/tree#/properties/children',
                                     'errors': [{'valid': True,
                                                 'instanceLocation': '/children',
                                                 'keywordLocation': '/$ref/properties/children/type',
                                                 'absoluteKeywordLocation': 'https://example.com/tree#/properties/children/type'},
                                                {'valid': False,
                                                 'instanceLocation': '/children',
                                                 'keywordLocation': '/$ref/properties/children/items',
                                                 'absoluteKeywordLocation': 'https://example.com/tree#/properties/children/items',
                                                 'error': [0],
                                                 'errors': [{'valid': False,
                                                             'instanceLocation': '/children/0',
                                                             'keywordLocation': '/$ref/properties/children/items/$dynamicRef',
                                                             'absoluteKeywordLocation': 'https://example.com/strict-tree',
                                                             'errors': [{'valid': True,
                                                                         'instanceLocation': '/children/0',
                                                                         'keywordLocation': '/$ref/properties/children/items/$dynamicRef/$ref',
                                                                         'absoluteKeywordLocation': 'https://example.com/tree',
                                                                         'annotations': [{'valid': True,
                                                                                          'instanceLocation': '/children/0',
                                                                                          'keywordLocation': '/$ref/properties/children/items/$dynamicRef/$ref/type',
                                                                                          'absoluteKeywordLocation': 'https://example.com/tree#/type'},
                                                                                         {'valid': True,
                                                                                          'instanceLocation': '/children/0',
                                                                                          'keywordLocation': '/$ref/properties/children/items/$dynamicRef/$ref/properties',
                                                                                          'absoluteKeywordLocation': 'https://example.com/tree#/properties',
                                                                                          'annotation': []}]},
                                                                        {'valid': False,
                                                                         'instanceLocation': '/children/0',
                                                                         'keywordLocation': '/$ref/properties/children/items/$dynamicRef/unevaluatedProperties',
                                                                         'absoluteKeywordLocation': 'https://example.com/strict-tree#/unevaluatedProperties',
                                                                         'error': ['daat']}]}]}]}]}]},
            {'valid': False,
             'instanceLocation': '',
             'keywordLocation': '/unevaluatedProperties',
             'absoluteKeywordLocation': 'https://example.com/strict-tree#/unevaluatedProperties',
             'error': ['children']}]}