Pydantic: Creating Model from standard dataclass

Created on 5 Oct 2020  路  7Comments  路  Source: samuelcolvin/pydantic

Assuming I have a layer or an internal package that exposes standard dataclasses, but now I need serialize, desserialize and validate this data. I would love use pydantic but it's annoying rewrite a Model or a pydantic.dataclasses with same body.

This scenario is possible when part of my library are not within my control (my company having several teams, and not all of them agreed using pydantic, but some of them provides libraries with standard dataclasses.

Besides that, I do not need runtime validation in every layer of my application

Something like:
dataclass.py

from dataclasses import dataclass

@dataclass
class Data:
    id: int
    name: str

In Application layer

from pydantic.dataclasses import parse_obj_to_dataclass

data: Data = parse_obj_to_dataclass({'id': 1, 'name': 'dnp1'}, Data)

# or 

model: Model[Data] = model_from_dataclass(Data)

model.parse_obj({'id':2, 'name': 'dnp1'})



It could be a generic function taking T and returning T

It make sense to you?

feature request

Most helpful comment

@dnp1 yes it will be a subclass
@torstenrudolf it should be possible easily as it will be a regular pydantic.dataclasses

@pydanticdataclass
@dataclass
class Data:
    id: int
    name: str

    @validator('name')
    def long_name(cls, name):
        assert len(name) > 10
        return name

Data(id='123', name='qwe')

# pydantic.error_wrappers.ValidationError: 1 validation error for Data
# name
#    (type=assertion_error)

or if you don't want to/can't touch the builtin dataclass

@dataclass
class Data:
    id: int
    name: str


@pydanticdataclass
class DataWithValidation(Data):
    @validator('name')
    ...

Did I misunderstand your question?

All 7 comments

Hello @dnp1
Does https://github.com/samuelcolvin/pydantic/pull/1817 solve your problem ?

from dataclasses import dataclass
from pydantic.dataclasses import dataclass as pydanticdataclass

@dataclass
class Data:
    id: int
    name: str

DataclassWithValidation = pydanticdataclass(Data)
DataclassWithValidation(id='123', name='qwe')  # ok
PydanticModel = DataclassWithValidation.__pydantic_model__
PydanticModel.parse_obj({'id':2, 'name': 'dnp1'})  # ok

Hello @PrettyWood!

Yes it does.

I'll take a closer look at it.

static typing checkers will consider DataclassWithValidation a subclass of Data?

@dnp1 I let you have a look at the PR and try it out. I'm looking for feedback before writing the documentation. Any help is welcome 馃檪

@PrettyWood can't wait for your PR to merge :-)

I'm wondering now, if there would be a nice way to add additional (field)validators to the generated pydantic model?

@dnp1 yes it will be a subclass
@torstenrudolf it should be possible easily as it will be a regular pydantic.dataclasses

@pydanticdataclass
@dataclass
class Data:
    id: int
    name: str

    @validator('name')
    def long_name(cls, name):
        assert len(name) > 10
        return name

Data(id='123', name='qwe')

# pydantic.error_wrappers.ValidationError: 1 validation error for Data
# name
#    (type=assertion_error)

or if you don't want to/can't touch the builtin dataclass

@dataclass
class Data:
    id: int
    name: str


@pydanticdataclass
class DataWithValidation(Data):
    @validator('name')
    ...

Did I misunderstand your question?

If anyone wants this, this is the way to do it since v1.7

from typing import Type

from pydantic import BaseModel
from pydantic.dataclasses import dataclass as pydantic_dataclass


def model_from_dataclass(kls: 'StdlibDataclass') -> Type[BaseModel]:
    """Converts a stdlib dataclass to a pydantic BaseModel"""
    return pydantic_dataclass(kls).__pydantic_model__

This function could be added directly in _pydantic_ if there are many upvotes I reckon

Was this page helpful?
0 / 5 - 0 ratings