pythonjsonschema

Python jsonschema with definitions


I'm validating a JSON schema, but the schema uses "Definitions", as in the example below. Using schema validation sites everything is ok, but in code with jsonschema I have the error:

PointerToNowhere: '/definitions/ipv4_pattern' does not exist inside {}

Does jsonschema not work with definitions?

import jsonschema

def main():
    str_json_yaml= {
                      "version": 1,
                      "group": "infrastructure",
                      "service": "monitoring",
                      "tech": "172.21.101.155"}

    str_json_schema = {
                      "$schema": "http://json-schema.org/draft-04/schema#",
                      "type": "object",
                      "properties": {
                        "version": {
                          "type": "integer"
                        },
                        "group": {
                          "type": "string"
                        },
                        "service": {
                          "type": "string"
                        },
                        "tech": { "$ref": "#/definitions/ipv4_pattern" }
                      },
                      "definitions": {
                            "ipv4_pattern": {"type": "string",
                                             "pattern": "^(?=\\d+\\.\\d+\\.\\d+\\.\\d+$)(?:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])\\.?){4}$"
                                            }
                      }
                    }

    validator = jsonschema.Draft202012Validator({})
    obj_return = validator.evolve(schema=str_json_schema)

    lst_errors = []
    for error in obj_return.iter_errors(str_json_yaml):
        lst_errors.append('Item: ' + error.json_path + ' / Error: ' + error.message)
    if len(lst_errors) > 0:
        print(*lst_errors, sep='\n')
        return False
    else:
        return True

if __name__ == "__main__":
    print(main())

Solution

  • Following jasonharper's comment, the problem was indeed evolve, I followed the examples on the module page, but evolve really has a situation with REFS and in this case, I should declare the schema in the Draft202012Validator method call and not in evolve.

    import jsonschema
    
    def main():
        str_json_yaml= {
                          "version": 1,
                          "group": "infrastructure",
                          "service": "monitoring",
                          "tech": "272.21.101.155"}
    
        str_json_schema = {
                          "$schema": "http://json-schema.org/draft-04/schema#",
                          "type": "object",
                          "properties": {
                            "version": {
                              "type": "integer"
                            },
                            "group": {
                              "type": "string"
                            },
                            "service": {
                              "type": "string"
                            },
                            "tech": { "$ref": "#/definitions/ipv4_pattern" }
                          },
                          "definitions": {
                                "ipv4_pattern": {"type": "string",
                                                 "pattern": "^(?=\\d+\\.\\d+\\.\\d+\\.\\d+$)(?:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])\\.?){4}$"
                                                }
                          }
                        }
    
        validator = jsonschema.Draft202012Validator(str_json_schema)
        obj_return = validator.evolve()
    
        lst_errors = []
        for error in obj_return.iter_errors(str_json_yaml):
            lst_errors.append('Item: ' + error.json_path + ' / Error: ' + error.message)
        if len(lst_errors) > 0:
            print(*lst_errors, sep='\n')
            return False
        else:
            return True
    
    if __name__ == "__main__":
        print(main())