Skip to content

custom validator/process functions for definitions #458

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
graingert opened this issue Sep 4, 2018 · 9 comments
Closed

custom validator/process functions for definitions #458

graingert opened this issue Sep 4, 2018 · 9 comments

Comments

@graingert
Copy link

graingert commented Sep 4, 2018

import jsonschema

class AddressValidationError extends jsonschema.ValidationError:
    pass

def process_address(address):
    if valid_physical_address(address):
        return Address(address)
    raise ValidationError(address)

schema = {
  "definitions": {
    "address": {
      jsonschema.process: validate_address,
      "type": "object",
      "properties": {
        "street_address": {
          "type": "string"
        },
        "city": {
          "type": "string"
        },
        "state": {
          "type": "string"
        }
      },
      "required": [
        "street_address",
        "city",
        "state"
      ]
    },
    "node": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string"
        },
        "children": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/node"
          }
        }
      }
    }
  },
  "type": "object",
  "properties": {
    "billing_address": {
      "title": "Billing address",
      "$ref": "#/definitions/address"
    },
    "shipping_address": {
      "title": "Shipping address",
      "$ref": "#/definitions/address"
    },
    "tree": {
      "title": "Recursive references",
      "$ref": "#/definitions/node"
    }
  }
}
@graingert
Copy link
Author

with the above schema, I'll be able to define a custom validator function and get data binding to custom classes

@graingert
Copy link
Author

graingert commented Sep 4, 2018

my actual usecase is taking a django ModelForm, using the fields to generate jsonschema and using the form clean/save methods etc to generate instances.

@graingert
Copy link
Author

graingert commented Sep 4, 2018

it avoids being incompatible with future jsonschema properties by using a Symbol object, that can be skipped in JSON serialization:

# jsonschema/__init__.py

class Symbol(object):
    __slots__ = []

process = Symbol()
process_bulk = Symbol()

@graingert
Copy link
Author

other option is a class like:

import jsonschema

class AddressValidationError extends jsonschema.ValidationError:
    pass

def process_address(address):
    if valid_physical_address(address):
        return Address(address)
    raise ValidationError(address)

schema = {
  "definitions": {
    "address": jsonschema.Process(process_address, {
      "type": "object",
      "properties": {
        "street_address": {
          "type": "string"
        },
        "city": {
          "type": "string"
        },
        "state": {
          "type": "string"
        }
      },
      "required": [
        "street_address",
        "city",
        "state"
      ]
    }),
    "node": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string"
        },
        "children": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/node"
          }
        }
      }
    }
  },
  "type": "object",
  "properties": {
    "billing_address": {
      "title": "Billing address",
      "$ref": "#/definitions/address"
    },
    "shipping_address": {
      "title": "Shipping address",
      "$ref": "#/definitions/address"
    },
    "tree": {
      "title": "Recursive references",
      "$ref": "#/definitions/node"
    }
  }
}

@Julian
Copy link
Member

Julian commented Sep 18, 2018

I have to read this a bit more carefully, but at first glance it seems like possibly you're talking about the sorts of things that Seep does / did / was envisioned to do -- namely, more geared towards transforming instances using defined rules rather than strictly validation.

@graingert
Copy link
Author

graingert commented Sep 18, 2018 via email

@schneidersoft
Copy link

schneidersoft commented Oct 13, 2018

I like the first implementation better, where the processor function is given as an attribute of the thing it's supposed to process.

This means the schema can still be traversed manually easily.

I have a use case for this involving hashes. I get some data like:
{'hash':'deadbeef'}
and want to get a python object like
{'hash':bytes.fromhex('deadbeef')}

a single validate+process schema would be nice

{'type':'object',
'properties':{
'hash':{'type':'string', processor:bytes.fromhex}
}
}

-edit-

Better yet. Just let me define new types and let me set processors for them. like:

{'type':'object',
'properties':{
'hash':{'type':'hashtype'}
}
}

@schneidersoft
Copy link

#475 someone else has a similar issue with dates

@Julian
Copy link
Member

Julian commented Oct 14, 2018

See my comment there and in previous issues -- I think this is in fact still a request for the types of things in Seep, in which case I would definitely be open to pull requests there to add any desired functionality.

If anything is missing in this library preventing this type of functionality from being implemented on top, that'd certainly be the kind of thing I'd accept bug reports for and want to add here, but the actual transformation itself is the kind of thing that belongs externally in a second package. This one is intended to strictly be an implementation of the specifications.

@Julian Julian closed this as completed Oct 14, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants