-
Notifications
You must be signed in to change notification settings - Fork 21
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
Support Data Classes Generation (A.K.A POPO/DTO) #33
Comments
Here is a nice POC for Python 3.6.2 where you can reify schema into attrs class having the same structure. from typing import TypeVar, Type
import attr
import jsl
import jsonschema
class Demo(jsl.Document):
"""
Demo schema
"""
ip = jsl.IPv4Field(required=True)
"""IPv4 address string"""
headers = jsl.DictField(required=True,
min_properties=1,
additional_properties=jsl.StringField())
"""Dictionary of HTTP headers"""
email = jsl.EmailField()
"""Optional User email"""
T = TypeVar('T') # Nice hack using generic type hinting. It preserves auto-completion
def reify(schema: Type[T], data: dict) -> T:
"""
Consumes JSON schema (as jsl.Document object) with dictionary data for validation
and if data is valid then “attrs” instance is produced having same structure
as schema object with populated data.
:param T schema: Schema type (as jsl.Document type.)
:param dict data: Data dictionary for validation against **schema**.
:return: Schema transformed into equivalent **attrs** instance with populated
**data**.
:rtype: T
:raises: ValueError — When **data** does not conforms with **schema**.
"""
try:
jsonschema.validate(data, schema.get_schema())
props = [name for name, _ in schema.get_schema()['properties'].items()]
fields = {key: attr.ib(default=None) for key in props}
# noinspection PyTypeChecker
return attr.make_class(schema.__name__, fields)(**data)
except jsonschema.ValidationError as e:
raise ValueError(f'Payload does not conform to JSON schema: {e.message}')
demo = reify(Demo, {'ip': '1.2.3.4', 'headers': {'Accept': '*/*'}})
print(demo)
print(f"{demo.ip} Headers: {demo.headers} Email {demo.email}")
# Prints:
# Demo(ip='1.2.3.4', headers={'Accept': '*/*'}, email=None)
# 1.2.3.4 Headers: {'Accept': '*/*'} Email None |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Defining JSON schema in JSL is very similar to defining your data class (DTO/POPO) using the attrs library but JSL only gives you JSON schema for validation.
Once payload was validated using JSL object it would make sense to work with data using data class rather than a big dictionary.
It would be super awesome to marry JSL with Attrs and have an ability not only having JSON schema generation but also a data class using the attrs library.
The text was updated successfully, but these errors were encountered: