Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I best send Pydantic model objects via put requests?

I am quite new to Pydantic. I have noticed how it is often used in validating input to FastAPI.

I have a project where I need to send something to another application's API endpoint and thought I would try structuring my data via a model class that inherits from Pydantic's BaseModel.

I try something like this (MWE):

from uuid import UUID

import requests
from pydantic import BaseModel


class Item(BaseModel):
    id: UUID
    content: str


item = Item(id=UUID(int=1), content="Something")

Now if I try put'ing the object like this:

requests.put("http://localhost", json=item)

it complains with a TypeError saying that "Object of type Item is not JSON serializable". (It does not matter for the purpose of this demonstration that there is no one listening at 'localhost'.) OK, this is easy enough to work around:

requests.put("http://localhost", data=item.model_dump_json())

It turns out I need to put a list of Items and then it would be convenient to do something like this, which I cannot due to the error in the first example:

requests.put("http://localhost", json=[item, item])

This becomes somewhat more involved to do via serialising the individual Items.

This makes me wonder: is this the way I should be doing it at all? Probably not, how is it supposed to be done?

Is it the wrong choice in the first place to involve Pydantic here?

like image 763
Thomas Arildsen Avatar asked Sep 02 '25 03:09

Thomas Arildsen


1 Answers

It's fine to use Pydantic for such a purpose. Your example looks also fine. Just do the following:

items = [Item(...), Item(...)]

requests.put("http://localhost", json=[item.dict() for item in items)])

Or you can even do something like this to skip list comprehensions in requests if you manage the format.

class Items(BaseModel):
    data: list[Item]


items = Items(data=[Item(...), Item(...)])
items.dict()

If you have UUID fields you probably need to convert it to str. There are a lot of ways to do it, so I'll just provide an example:

class Item(BaseModel):
    id: UUID4
    content: str

    @model_serializer
    def dump(self) -> dict:
        return {
            "id": str(self.id),  # Can be done via validator, etc.
            "content": self.content
        }

UPD: I found another approach that I didn't know about before:

pydantic_core.to_jsonable_python([Item(...), Item(...)])
like image 110
Victor Egiazarian Avatar answered Sep 04 '25 18:09

Victor Egiazarian