json-schema-org/json-schema-org.github.io

how to use $ref from a definitions.json file (python code)

yuzhujiutian opened this issue · 1 comments

in document: https://json-schema.org/understanding-json-schema/structuring.html

one line write:

$ref can also be a relative or absolute URI, so if you prefer to include your definitions in separate files, you can also do that. For example:

{ "$ref": "definitions.json#/address" }

My exercise code is as follows: (environment: jupyter lab, python 3.7)

  1. definitions.json
{
    "address": {
        "type": "object",
        "properties": {
            "street_address": {
                "type": "string"
            },
            "city": {
                "type": "string"
            },
            "state": {
                "type": "string"
            }
        },
        "required": [
            "street_address",
            "city",
            "state"
        ]
    }
}
  1. python code
from jsonschema import validate
from jsonschema.validators import Draft7Validator
from jsonschema.exceptions import ValidationError, SchemaError

# https://json-schema.org/understanding-json-schema/UnderstandingJSONSchema.pdf -> 5.1 Reuse
# Description: definitions can be defined before or after properties.

sch = {
    "$schema": "http://json-schema.org/draft-07/schema#",
    
    "type": "object",
    
    "properties": {
        "billing_address": {
            "$ref": "#/definitions/address"
        },
        "shipping_address": {
            "$ref": "#/definitions/address"
        }
    },
    
    "definitions": {
        "address": {
            "type": "object",
            "properties": {
                "street_address": {
                    "type": "string"
                },
                "city": {
                    "type": "string"
                },
                "state": {
                    "type": "string"
                }
            },
            "required": [
                "street_address",
                "city",
                "state"
            ]
        }
    }
}

sch2 = {
    "$schema": "http://json-schema.org/draft-07/schema#",
    
    "type": "object",
    
    "properties": {
        "billing_address": {
            "$ref": "definitions.json#/address"
        },
        "shipping_address": {
            "$ref": "definitions.json#/address"
        }
    }
}


ins = {
    "shipping_address": {
        "street_address": "1600 Pennsylvania Avenue NW",
        "city": "Washington",
        "state": "DC"
    },
    "billing_address": {
        "street_address": "1st Street SE",
        "city": "Washington",
        "state": "DC"
    }
}

# case 1, OK
validator = Draft7Validator(schema = sch)
tmp = validator.validate(instance = ins)
print(tmp)

# case 2, NOK
validator = Draft7Validator(schema = sch2)
tmp = validator.validate(instance = ins)
print(tmp)
  1. run case 2, but error
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
D:\winusr\anaconda\anaconda3_201910\envs\wanmore\lib\site-packages\jsonschema\validators.py in resolve_from_url(self, url)
    773         try:
--> 774             document = self.store[url]
    775         except KeyError:

D:\winusr\anaconda\anaconda3_201910\envs\wanmore\lib\site-packages\jsonschema\_utils.py in __getitem__(self, uri)
     21     def __getitem__(self, uri):
---> 22         return self.store[self.normalize(uri)]
     23 

KeyError: 'definitions.json'

During handling of the above exception, another exception occurred:

ValueError                                Traceback (most recent call last)
D:\winusr\anaconda\anaconda3_201910\envs\wanmore\lib\site-packages\jsonschema\validators.py in resolve_from_url(self, url)
    776             try:
--> 777                 document = self.resolve_remote(url)
    778             except Exception as exc:

D:\winusr\anaconda\anaconda3_201910\envs\wanmore\lib\site-packages\jsonschema\validators.py in resolve_remote(self, uri)
    862             # Otherwise, pass off to urllib and assume utf-8
--> 863             with urlopen(uri) as url:
    864                 result = json.loads(url.read().decode("utf-8"))

D:\winusr\anaconda\anaconda3_201910\envs\wanmore\lib\urllib\request.py in urlopen(url, data, timeout, cafile, capath, cadefault, context)
    221         opener = _opener
--> 222     return opener.open(url, data, timeout)
    223 

D:\winusr\anaconda\anaconda3_201910\envs\wanmore\lib\urllib\request.py in open(self, fullurl, data, timeout)
    509         if isinstance(fullurl, str):
--> 510             req = Request(fullurl, data)
    511         else:

D:\winusr\anaconda\anaconda3_201910\envs\wanmore\lib\urllib\request.py in __init__(self, url, data, headers, origin_req_host, unverifiable, method)
    327                  method=None):
--> 328         self.full_url = url
    329         self.headers = {}

D:\winusr\anaconda\anaconda3_201910\envs\wanmore\lib\urllib\request.py in full_url(self, url)
    353         self._full_url, self.fragment = splittag(self._full_url)
--> 354         self._parse()
    355 

D:\winusr\anaconda\anaconda3_201910\envs\wanmore\lib\urllib\request.py in _parse(self)
    382         if self.type is None:
--> 383             raise ValueError("unknown url type: %r" % self.full_url)
    384         self.host, self.selector = splithost(rest)

ValueError: unknown url type: 'definitions.json'

During handling of the above exception, another exception occurred:

RefResolutionError                        Traceback (most recent call last)
<ipython-input-1-42ea6f09d3f9> in <module>
     73 
     74 validator = Draft7Validator(schema = sch2)
---> 75 tmp = validator.validate(instance = ins)
     76 print(tmp)

D:\winusr\anaconda\anaconda3_201910\envs\wanmore\lib\site-packages\jsonschema\validators.py in validate(self, *args, **kwargs)
    350 
    351         def validate(self, *args, **kwargs):
--> 352             for error in self.iter_errors(*args, **kwargs):
    353                 raise error
    354 

D:\winusr\anaconda\anaconda3_201910\envs\wanmore\lib\site-packages\jsonschema\validators.py in iter_errors(self, instance, _schema)
    326 
    327                     errors = validator(self, v, instance, _schema) or ()
--> 328                     for error in errors:
    329                         # set details if not already set by the called fn
    330                         error._set(

D:\winusr\anaconda\anaconda3_201910\envs\wanmore\lib\site-packages\jsonschema\_validators.py in properties(validator, properties, instance, schema)
    284                 subschema,
    285                 path=property,
--> 286                 schema_path=property,
    287             ):
    288                 yield error

D:\winusr\anaconda\anaconda3_201910\envs\wanmore\lib\site-packages\jsonschema\validators.py in descend(self, instance, schema, path, schema_path)
    342 
    343         def descend(self, instance, schema, path=None, schema_path=None):
--> 344             for error in self.iter_errors(instance, schema):
    345                 if path is not None:
    346                     error.path.appendleft(path)

D:\winusr\anaconda\anaconda3_201910\envs\wanmore\lib\site-packages\jsonschema\validators.py in iter_errors(self, instance, _schema)
    326 
    327                     errors = validator(self, v, instance, _schema) or ()
--> 328                     for error in errors:
    329                         # set details if not already set by the called fn
    330                         error._set(

D:\winusr\anaconda\anaconda3_201910\envs\wanmore\lib\site-packages\jsonschema\_validators.py in ref(validator, ref, instance, schema)
    257                 yield error
    258     else:
--> 259         scope, resolved = validator.resolver.resolve(ref)
    260         validator.resolver.push_scope(scope)
    261 

D:\winusr\anaconda\anaconda3_201910\envs\wanmore\lib\site-packages\jsonschema\validators.py in resolve(self, ref)
    764         """
    765         url = self._urljoin_cache(self.resolution_scope, ref)
--> 766         return url, self._remote_cache(url)
    767 
    768     def resolve_from_url(self, url):

D:\winusr\anaconda\anaconda3_201910\envs\wanmore\lib\site-packages\jsonschema\validators.py in resolve_from_url(self, url)
    777                 document = self.resolve_remote(url)
    778             except Exception as exc:
--> 779                 raise exceptions.RefResolutionError(exc)
    780 
    781         return self.resolve_fragment(document, fragment)

RefResolutionError: unknown url type: 'definitions.json'

image

Hi -- sorry you're having trouble.

Come talk to us on the JSON Schema Slack and someone will likely try and help, or otherwise perhaps give StackOverflow a shot as well if you're more comfortable there.

This repository though is one for the JSON Schema website, and specifically for issues or feature requests for it, not general JSON Schema questions.

Someone in one of the other more suitable forums for questions will likely be happy to help though!