5 Effective Ways to Convert Python Dict to Pydantic Model

πŸ’‘ Problem Formulation: You’re working with Python and need to convert a dictionary to a Pydantic model for validation, serialization, and documentation purposes. For instance, you have a dict like {"name": "John Doe", "age": 30} and you need to transform it into a Pydantic model that ensures “name” is a string and “age” is an integer. This article provides solutions to achieve this.

Method 1: Using Pydantic’s BaseModel

Pydantic’s BaseModel is designed for data parsing and validation. By defining a Pydantic model class that extends BaseModel and includes type annotations, you can easily convert a dictionary into a Pydantic object that’s validated against the specified schema.

Here’s an example:

from pydantic import BaseModel

class User(BaseModel):
    name: str
    age: int

user_dict = {"name": "John Doe", "age": 30}
user_model = User(**user_dict)
print(user_model)

Output:

name='John Doe' age=30

In the example above, we define a User class that extends BaseModel, indicating that “name” should be a string and “age” should be an integer. The provided dictionary is unpacked and passed to the User class, which automatically validates and creates a Pydantic model instance.

Method 2: Using Pydantic’s parse_obj

The parse_obj method of a Pydantic model can be used for creating model instances from dictionaries. It is a class method that accepts a dictionary and returns a validated model instance.

Here’s an example:

from pydantic import BaseModel

class User(BaseModel):
    name: str
    age: int

user_dict = {"name": "Alice", "age": 28}
user_model = User.parse_obj(user_dict)
print(user_model)

Output:

name='Alice' age=28

The code snippet demonstrates how the parse_obj class method is called with the dictionary user_dict. This method ensures the dictionary adheres to the model’s structure before creating an instance of the User model.

Method 3: Using Pydantic’s construct method

The construct method is another Pydantic functionality that allows you to create a model without validation. This is useful for performance-critical situations where you’re certain the data is already valid.

Here’s an example:

from pydantic import BaseModel

class User(BaseModel):
    name: str
    age: int

user_dict = {"name": "Bob", "age": 25}
user_model = User.construct(**user_dict)
print(user_model)

Output:

name='Bob' age=25

We utilize the construct method to create an instance of the User class, bypassing validation. This can lead to better performance, but it’s crucial to ensure the data is valid beforehand to avoid errors.

Method 4: Using Pydantic’s from_orm

Pydantic can convert ORM model instances to Pydantic models using the from_orm method. This is particularly useful when working with databases and ORMs, such as SQLAlchemy.

Here’s an example:

from pydantic import BaseModel

class ORMSimulatedUser:
    def __init__(self, name, age):
        self.name = name
        self.age = age
   
class User(BaseModel):
    name: str
    age: int

orm_user = ORMSimulatedUser(name="Eve", age=22)
user_model = User.from_orm(orm_user)
print(user_model)

Output:

name='Eve' age=22

In this example, we simulate an ORM object, orm_user, and convert it into a Pydantic model using the from_orm method. This method is useful for integrating Pydantic with an existing ORM.

Bonus One-Liner Method 5: Dynamic Model Creation

You can dynamically create Pydantic models using the create_model utility function. This is particularly useful when the structure of the model is not known ahead of time or needs to be generated on the fly.

Here’s an example:

from pydantic import create_model

user_dict = {"name": "Charlie", "age": 40}
DynamicUser = create_model('DynamicUser', **{k: (type(v), ...) for k, v in user_dict.items()})
user_model = DynamicUser(**user_dict)
print(user_model)

Output:

name='Charlie' age=40

Using the create_model function, we dynamically create a Pydantic model class, DynamicUser, based on the keys and types of values present in the user_dict. Then, we instantiate this model passing the original dictionary as arguments.

Summary/Discussion

  • Method 1: Using BaseModel. This is the most straightforward and typical approach. It’s great for simple conversions but requires upfront model definitions.
  • Method 2: Using parse_obj. Provides a clear intent with explicit parsing which is very readable. It performs validation, which can add overhead.
  • Method 3: Using construct method. Offers great performance by skipping validation. However, there’s a risk of creating invalid model instances if the data hasn’t been validated elsewhere.
  • Method 4: Using from_orm. Handy for integrating with ORMs, bridging database models with Pydantic. It relies on having compatible ORM instances that can be limiting.
  • Bonus Method 5: Dynamic Model Creation. Exceptionally flexible and powerful for generating models dynamically. It can be complex and harder to maintain due to its dynamic nature.