Define a Pydantic (nested) model

Viewed 5572

If I use GET (given an id) I get a JSON like:

{
    "data": {
        "id": "81",
        "ks": {
            "k1": 25,
            "k2": 5
        },
        "items": [
            {
                "id": 1,
                "name": "John",
                "surname": "Smith"
            },
            {
                "id": 2,
                "name": "Jane",
                "surname": "Doe"
            }
        ]
    },
    "server-time": "2021-12-09 14:18:40"
}

with the particular case (if id does not exist):

{
    "data": {
        "id": -1,
        "ks": "",
        "items": []
    },
    "server-time": "2021-12-10 09:35:22"
}

I would like to create a Pydantic model for managing this data structure (I mean to formally define these objects). What is the smartest way to manage this data structure by creating classes (possibly nested)?

4 Answers

If you don't need data validation that pydantic offers, you can use data classes along with the dataclass-wizard for this same task. It's slightly easier as you don't need to define a mapping for lisp-cased keys such as server-time.

Simple example below:

from __future__ import annotations

from dataclasses import dataclass
from datetime import datetime

from dataclass_wizard import fromdict


@dataclass
class Something:
    data: Data
    # or simply:
    #   server_time: str
    server_time: datetime


@dataclass
class Data:
    id: int
    ks: dict[str, int]
    items: list[Person]


@dataclass
class Person:
    id: int
    name: str
    surname: str


# note: data is defined in the OP above
input_data = ...

print(fromdict(Something, input_data))

Output:

Something(data=Data(id=81, ks={'k1': 25, 'k2': 5}, items=[Person(id=1, name='John', surname='Smith'), Person(id=2, name='Jane', surname='Doe')]), server_time=datetime.datetime(2021, 12, 9, 14, 18, 40))

I see that you have taged fastapi and pydantic so i would sugest you follow the official Tutorial to learn how fastapi work. You have a whole part explaining the usage of pydantic with fastapi here.

to respond more precisely to your question pydantic models are well explain in the doc.

simple exemple:

from typing import List
from pydantic import BaseModel

class Data(BaseModel):
    id: int
    ks: str
    items: List[str]

class Something(BaseModel):
    data: Data
    # you can replace it by a pydantic time type that fit your need
    server_time: str = Field(alias="server-time")

I recommend going through the official tutorial for an in-depth look at how the framework handles data model creation and validation with pydantic.

To answer your question:

from datetime import datetime
from typing import List
from pydantic import BaseModel


class K(BaseModel):
    k1: int
    k2: int


class Item(BaseModel):
    id: int
    name: str
    surname: str


class DataModel(BaseModel):
    id: int = -1
    ks: K = None
    items: List[Item] = []
    server_time: datetime = datetime.now()

from pydantic import BaseModel

class User(BaseModel):
    id: int
    name = "Jane Doe"
Related