Skip to content
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

Consider adding "pydantic" as built-in serialization / deserialization option #146

Closed
senpos opened this issue Mar 2, 2019 · 1 comment · Fixed by #200
Closed

Consider adding "pydantic" as built-in serialization / deserialization option #146

senpos opened this issue Mar 2, 2019 · 1 comment · Fixed by #200

Comments

@senpos
Copy link

senpos commented Mar 2, 2019

Problem

At the moment, if you want to deserialize your input data into object using marshmallow you have to do double-work: create a schema and create a similar to the schema class. Even worse, if you need to change your fields, you have to sync changes in two places.

For all examples, we have the same input:

input_json = """
[
    {
        "name": "John",
        "age": 42,
        "is_employed": true

    },
    {
        "name": "Sarah",
        "age": 24,
        "is_employed": false

    }
]
"""

This is how you create a list of User objects with marshmallow:

from marshmallow import Schema, fields, post_load
from collections import namedtuple

User = namedtuple("User", "name age is_employed")

class UserSchema(Schema):
    name = fields.String()
    age = fields.Integer()
    is_employed = fields.Boolean(default=False)

    @post_load
    def make_user(self, data):
        return User(**data)

user_schema = UserSchema(many=True)
users = user_schema.loads(input_json)
print(users.data)

How can we avoid this

With pydantic, you can do the following:

import json
from pydantic import BaseModel, Schema

class User(BaseModel):
    name: str
    age: int
    is_employed: bool = False

users = [User(**item) for item in json.loads(input_json)]
print(users)

You describe your model once and you are ready to go. If you want more control over your fields - there's a schema for this (its like fields in Marshmallow, I guess).

More info about pydantic

Cool think that you use native type hints for its description. If you are fan of dataclasses in Python 3.7 - they have that too. Also, they are fast.
The project is still kind of young, but powerful already.

@senpos
Copy link
Author

senpos commented Mar 2, 2019

At the moment, I am using the next converter:

import pydantic
import uplink

@uplink.install
class PydanticFactory(uplink.converters.Factory):
    """Adapter for pydantic (https://pydantic-docs.helpmanual.io/)."""

    def create_response_body_converter(self, cls, request_definition):
        def convert(response):
            json_resp = response.json()
            if isinstance(json_resp, list):
                return [cls(**item) for item in json_resp]
            return cls(**json_resp)

        return convert

    def create_request_body_converter(self, cls, request_definition):
        return lambda obj: obj.json

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants