Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jsonschema RefResolver to resolve multiple refs in python

How may we validate multiple refs in a schema using jsonschema.RefResolver?

I have a validation script that works good if I have one ref in a file. I now have two or three refs in a schema, that are in a different directory.

base_dir = '/schema/models/'
with open (os.path.join(base_dir, 'Defined.json')) as file_object:
    schema = json.load(file_object)
    resolver = jsonschema.RefResolver('file://' + base_dir + '/' + 'Fields/Ranges.json', schema)
    jsonschema.Draft4Validator(schema, resolver=resolver).validate(data)

My json schema:

{
  "properties": {
    "description": {
        "type": "object",
        "after": {"type": ["string", "null"]},
        "before": {"type": "string"}
      },
      "width": {"type": "number"} ,
      "range_specifier": {"type": "string"},
      "start": {"type": "number", "enum" : [0, 1] } ,
      "ranges": {
        "$ref": "Fields/Ranges.json"
      },
      "values": {
        "$ref": "Fields/Values.json"
      }
  }
}

So my question is should I have two resolvers one for ranges and one for values and call the resolvers separately in Draft4Validator ? Or is there a better way to do this?

like image 500
repop_rev Avatar asked Sep 03 '26 09:09

repop_rev


1 Answers

I've spent several hours on the same issue myself so I hope that this workaround is useful for others

def validate(schema_search_path, json_data, schema_id):
    """
    load the json file and validate against loaded schema
    """
    try:
        schemastore = {}
        schema = None
        fnames = os.listdir(schema_search_path)
        for fname in fnames:
            fpath = os.path.join(schema_search_path, fname)
            if fpath[-5:] == ".json":
                with open(fpath, "r") as schema_fd:
                    schema = json.load(schema_fd)
                    if "id" in schema:
                        schemastore[schema["id"]] = schema

        schema = schemastore.get("http://mydomain/json-schema/%s" % schema_id)
        Draft4Validator.check_schema()
        resolver = RefResolver("file://%s.json" % os.path.join(schema_search_path, schema_id), schema, schemastore)
        Draft4Validator(schema, resolver=resolver).validate(json_data)
        return True
    except ValidationError as error:
        # handle validation error 
        pass
    except SchemaError as error:
        # handle schema error
        pass
    return False

Every JSON schema that should be used in path resolution has an ID element that must be passed to validate as schema_id argument

  "id": "http://mydomain/json-schema/myid"

All the schema are loaded in a dict and then passed to the resolver as a store. In your example you should also load the schema from the other directory.

like image 170
s1m0 Avatar answered Sep 04 '26 23:09

s1m0