python-jsonschema / jsonschema

An implementation of the JSON Schema specification for Python
https://python-jsonschema.readthedocs.io
MIT License
4.58k stars 578 forks source link

validate() throwing exception for a valid schema #1206

Closed port-b closed 8 months ago

port-b commented 8 months ago

I am trying to validate python dicts, to check if they are a valid JSON schema. I pulled a schema from https://json-schema.org/learn/miscellaneous-examples#complex-object-with-nested-properties to test it with here is my code:

import jsonschema

input_schema = {
    "$id": "https://example.com/complex-object.schema.json",
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "title": "Complex Object",
    "type": "object",
    "properties": {
        "name": {
            "type": "string"
        },
        "age": {
            "type": "integer",
            "minimum": 0
        },
        "address": {
            "type": "object",
            "properties": {
                "street": {
                    "type": "string"
                },
                "city": {
                    "type": "string"
                },
                "state": {
                    "type": "string"
                },
                "postalCode": {
                    "type": "string",
                    "pattern": "\\d{5}"
                }
            },
            "required": ["street", "city", "state", "postalCode"]
        },
        "hobbies": {
            "type": "array",
            "items": {
                "type": "string"
            }
        }
    },
    "required": ["name", "age"]
}

try:
    validator = jsonschema.Draft7Validator.META_SCHEMA
    jsonschema.validate(validator, input_schema)
    print("Valid schema")

except jsonschema.exceptions.ValidationError as e:
    print("Invalid")
    print(f"{e}")

I am getting the following exception

Invalid
'name' is a required property

Failed validating 'required' in schema:
    {'$id': 'https://example.com/complex-object.schema.json',
     '$schema': 'https://json-schema.org/draft/2020-12/schema',
     'properties': {'address': {'properties': {'city': {'type': 'string'},
                                               'postalCode': {'pattern': '\\d{5}',
                                                              'type': 'string'},
                                               'state': {'type': 'string'},
                                               'street': {'type': 'string'}},
                                'type': 'object'},
                    'age': {'minimum': 0, 'type': 'integer'},
                    'hobbies': {'items': {'type': 'string'},
                                'type': 'array'},
                    'name': {'type': 'string'}},
     'required': ['name', 'age'],
     'title': 'Complex Object',
     'type': 'object'}

On instance:
    {'$id': 'http://json-schema.org/draft-07/schema#',
     '$schema': 'http://json-schema.org/draft-07/schema#',
     'default': True,
     'definitions': {'nonNegativeInteger': {'minimum': 0,
                                            'type': 'integer'},
                     'nonNegativeIntegerDefault0': {'allOf': [{'$ref': '#/definitions/nonNegativeInteger'},
                                                              {'default': 0}]},
                     'schemaArray': {'items': {'$ref': '#'},
                                     'minItems': 1,
                                     'type': 'array'},
                     'simpleTypes': {'enum': ['array',
                                              'boolean',
                                              'integer',
                                              'null',
                                              'number',
                                              'object',
                                              'string']},
                     'stringArray': {'default': [],
                                     'items': {'type': 'string'},
                                     'type': 'array',
                                     'uniqueItems': True}},
     'properties': {'$comment': {'type': 'string'},
                    '$id': {'format': 'uri-reference', 'type': 'string'},
                    '$ref': {'format': 'uri-reference', 'type': 'string'},
                    '$schema': {'format': 'uri', 'type': 'string'},
                    'additionalItems': {'$ref': '#'},
                    'additionalProperties': {'$ref': '#'},
                    'allOf': {'$ref': '#/definitions/schemaArray'},
                    'anyOf': {'$ref': '#/definitions/schemaArray'},
                    'const': True,
                    'contains': {'$ref': '#'},
                    'contentEncoding': {'type': 'string'},
                    'contentMediaType': {'type': 'string'},
                    'default': True,
                    'definitions': {'additionalProperties': {'$ref': '#'},
                                    'default': {},
                                    'type': 'object'},
                    'dependencies': {'additionalProperties': {'anyOf': [{'$ref': '#'},
                                                                        {'$ref': '#/definitions/stringArray'}]},
                                     'type': 'object'},
                    'description': {'type': 'string'},
                    'else': {'$ref': '#'},
                    'enum': {'items': True, 'type': 'array'},
                    'examples': {'items': True, 'type': 'array'},
                    'exclusiveMaximum': {'type': 'number'},
                    'exclusiveMinimum': {'type': 'number'},
                    'format': {'type': 'string'},
                    'if': {'$ref': '#'},
                    'items': {'anyOf': [{'$ref': '#'},
                                        {'$ref': '#/definitions/schemaArray'}],
                              'default': True},
                    'maxItems': {'$ref': '#/definitions/nonNegativeInteger'},
                    'maxLength': {'$ref': '#/definitions/nonNegativeInteger'},
                    'maxProperties': {'$ref': '#/definitions/nonNegativeInteger'},
                    'maximum': {'type': 'number'},
                    'minItems': {'$ref': '#/definitions/nonNegativeIntegerDefault0'},
                    'minLength': {'$ref': '#/definitions/nonNegativeIntegerDefault0'},
                    'minProperties': {'$ref': '#/definitions/nonNegativeIntegerDefault0'},
                    'minimum': {'type': 'number'},
                    'multipleOf': {'exclusiveMinimum': 0, 'type': 'number'},
                    'not': {'$ref': '#'},
                    'oneOf': {'$ref': '#/definitions/schemaArray'},
                    'pattern': {'format': 'regex', 'type': 'string'},
                    'patternProperties': {'additionalProperties': {'$ref': '#'},
                                          'default': {},
                                          'propertyNames': {'format': 'regex'},
                                          'type': 'object'},
                    'properties': {'additionalProperties': {'$ref': '#'},
                                   'default': {},
                                   'type': 'object'},
                    'propertyNames': {'$ref': '#'},
                    'readOnly': {'default': False, 'type': 'boolean'},
                    'required': {'$ref': '#/definitions/stringArray'},
                    'then': {'$ref': '#'},
                    'title': {'type': 'string'},
                    'type': {'anyOf': [{'$ref': '#/definitions/simpleTypes'},
                                       {'items': {'$ref': '#/definitions/simpleTypes'},
                                        'minItems': 1,
                                        'type': 'array',
                                        'uniqueItems': True}]},
                    'uniqueItems': {'default': False, 'type': 'boolean'}},
     'title': 'Core schema meta-schema',
     'type': ['object', 'boolean']}

I would expect this to be a valid schema?

Julian commented 8 months ago

You have your arguments reversed, so you validated the metaschema under your schema, rather than your schema under the metaschema.

You mean jsonschema.validate(input_schema, validator) or jsonschema.validators.Draft7Validator.check_schema(input_schema).