python-jsonschema / jsonschema

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

Reference to anchored subschema defined in oneOf #1138

Closed aw32 closed 1 year ago

aw32 commented 1 year ago

I tried to create a schema using oneOf containing an array subschema and an object subschema. To avoid the redundant definition of the contained objects, I wanted to reference the object subschema inside of the array subschema:

{
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "$id": "test.schema.json",
    "title": "Test schema",
    "description": "Test schema description",

    "oneOf": [
        {
            "$anchor": "rule",
            "type": "object",
            "properties":{
                "name": {
                    "description": "The unique name for a rule",
                    "type": "string"
                }
            },
            "required": ["name"]
        },
        {
            "type": "array",
            "items": {
                "$ref": "#rule"
            }
        }
    ]
}

It seems, the subschema with the $anchor rule is ignored, when evaluating the $ref #rule. The test JSON would be for the array:

[                                                                                                                                                                      
{"name": "foobar" },
{"name": "asdf" }
]

And for the object:

{ "name": "foobar" }

Using check-jsonschema --schemafile test.schema.json a.json with the array example gives the following error:

Failure resolving $ref within schema

_RefResolutionError: Unresolvable JSON pointer: 'rule'
  in "/opt/homebrew/Cellar/check-jsonschema/0.23.3/libexec/lib/python3.11/site-packages/check_jsonschema/checker.py", line 77
  >>> result = self._build_result()

  caused by

  KeyError: 'rule'
    in "/opt/homebrew/Cellar/check-jsonschema/0.23.3/libexec/lib/python3.11/site-packages/jsonschema/validators.py", line 1137
    >>> document = document[part]

Is this a bug in python-jsonschema or is my schema invalid?

Julian commented 1 year ago
from jsonschema import validate
schema = {
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "$id": "test.schema.json",
    "title": "Test schema",
    "description": "Test schema description",

    "oneOf": [
        {
            "$anchor": "rule",
            "type": "object",
            "properties": {
                "name": {
                    "description": "The unique name for a rule",
                    "type": "string"
                }
            },
            "required": ["name"]
        },
        {
            "type": "array",
            "items": {
                "$ref": "#rule"
            }
        }
    ]
}
validate(
    instance={ "name": "foobar" },
    schema=schema,
)

This code produces no errors with either of your examples. Can you explain what behavior you're expecting? Those look valid under the schema you showed to me.

aw32 commented 1 year ago

Oh, this is interesting. For me the example

instance=[{ "name": "foobar" },{"name":"asdf"}],

gives the forementioned error message.

Can you explain what behavior you're expecting?

I expect both examples to be valid according to the schema.

Julian commented 1 year ago

I don't see what code you're running -- though now I notice you're saying you're using check-jsonschema -- if that's where you're seeing this behavior and you check you're on a recent version this likely would belong on that repo.

aw32 commented 1 year ago

I confused the Python package location and used an outdated version of jsonschema. I updated to the newest version and now it works. Thanks for the very fast response. ❤️