datamodel-code-generator
datamodel-code-generator copied to clipboard
Support for adding validator decorator
Is your feature request related to a problem? Please describe.
pydantic
supports the provision to add a validator decorator for fields. Is there anyway to represent this in jsonschema
and data-model-generator will generate this. This can be treated as a custom-path
where decorator code will be present in the given path and during the model generation this method needs to be attached to the model(Not sure about this).
Describe the solution you'd like
- Support for specifying validator in
jsonschema
. - Need a provision to specify validators in the jsonschema and data-model generator should recognize this.
from pydantic import BaseModel, ValidationError, validator
class UserModel(BaseModel):
name: str
@validator('name', pre=True)
def name_must_contain_space(cls, v):
if ' ' not in v:
raise ValueError('must contain a space')
return v.title()
-
validator
name and args can be described injsonschema
andpath
to the code can be made custom, since it will contain other logic.
type: object
properties:
name:
type: string
x-validator:
type: object
properties:
name:
const: name_must_contain_space
path:
const: a.b.c._name_must_contain_space
args:
pre:
const: True
- With the above representation the validator logic can be declared in another method and a simple reference needs to be added in model. Like,
from pydantic import BaseModel, ValidationError, validator
from a.b.c import _name_must_contain_space
class UserModel(BaseModel):
name: str
@validator('name', pre=True)
def name_must_contain_space(cls, v, values, **kwargs):
return _name_must_contain_space(cls, v, values, **kwargs)
Describe alternatives you've considered
- For implementing this behaviour, generated models needs to be extended and need to add this validator method in the extended model.
@sarangsbabu367 Thank you for your suggestion. I feel it's a good idea. I will implement it when I finish other issues.
@koxudaxi May i open a pr for this ?
- Can you suggest some points to improve the validator representation in
yaml
, like currently there is an option forcustomTypePath
can we use a similar name likecustomValidator
? - Can we reduce the
yaml
format(minimalize) ?
Person:
type: object
customValidator:
type: object
properties:
path: a.b.c.person_root_validator
args:
pre: True
properties:
name:
type: string
customValidator:
type: object
properties:
path: a.b.c.name_must_contain_space
args:
pre: True
always: True
In the above example, we can support an option for root-level
validator. And option to give a validator name can be removed since there wont be much usecase(validator method name will be same as given by client)
Isn't it possible to just not "override" the "@validator" code whenever we generate the pydantic objects again?
Just adding "@validator" logic to the spec would not provide the flexibility that some examples might need. ie: in this case, we would want to validate if a given field matches a set of regexs.
openapi: 3.0.2
info:
title: Example 🐶
version: 1.0.0
paths: {}
components:
schemas:
example.Job:
title: Job
type: object
properties:
schedule:
title: Schedule
type: string
description: Frequency of cronjob. (@once to run 1 time, None to not run automatically)
example: 0 1 * * 1
# example.py
(...)
# added manually ----->
def compile_match_cron_expression(expression: str):
cron_re = re.compile(
r"(@(once|annually|yearly|monthly|weekly|daily|hourly|reboot))|((((\d+,)+\d+|(\d+(\/|-)\d+)|\d+|\*) ?){5,7})"
)
return cron_re.match(expression) or None
# <---------------------
class Job(BaseModel):
schedule: Optional[str] = Field(
None,
description='Frequency of cronjob. (@once to run 1 time, None to not run automatically)',
example='0 1 * * 1',
title='Schedule',
)
# added manually ----->
@validator("schedule")
def schedule_is_cron(cls, v):
if v:
assert compile_match_cron_expression(v), "Value provided is not a valid cron expression."
return v
# <---------------------
This could also solve this problem. Is this something that datamodel-codegen
allows today?