Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JSON dumping a dictionary where some values are PyDantic models

Assume a dictionary with an arbitrary structure, where some values are native Python objects and others are instances of PyDantic's BaseModel subclasses

e.g.

my_dict = {"key1": "value1",
           "key2": {"key3": pydantic_object1, 
                    "key4": 4},
           "key5": pydantic_object2}

I want to dump this dictionary to a JSON file. The naive solution of using BaseModel.model_dump() to convert first all the PyDantic objects to dictionaries and then using json.dump doesn't work, because some of the attributes of the PyDantic objects cannot be serialized by the native serializer, e.g. datetimess and other custom objects which their serializers are attached to the object's implementation.

I also couldn't figure out how to write a custom encoder that will user PyDantic's built in JSON encoder.

How would you solve this (PyDantic v2 and above)

like image 411
bluesummers Avatar asked Oct 12 '25 23:10

bluesummers


1 Answers

Came across this question due to a similar problem (where I had a dictionary of BaseModels), which I solved with TypeAdapter:

class SomePydanticClass1(BaseModel):
    some_int: int
    some_string: str

test: Dict[str, SomePydanticClass1] = get_dict()

with open("test.json", "wb") as test_json:
    ta = TypeAdapter(Dict[str, SomePydanticClass1])
    test_json.write(ta.dump_json(test, indent=4))

Since in your case the dictionary would contain arbitrary types, I tested the following code:

class SomePydanticClass1(BaseModel):
    some_int: int
    some_string: str


class SomePydanticClass2(BaseModel):
    some_float: float
    some_string: str

spc1 = SomePydanticClass1(some_int=1, some_string="foo")
spc2 = SomePydanticClass2(some_float=2.3, some_string="bar")

my_dict = {
    "key1": "value1",
    "key2": {"key3": spc1, "key4": 4},
    "key5": spc2,
}

with open("test.json", "wb") as test_json:
    ta = TypeAdapter(Dict[str, Any])
    test_json.write(ta.dump_json(my_dict, indent=4))

which puts out the following json file:

{
    "key1": "value1",
    "key2": {
        "key3": {
            "some_int": 1,
            "some_string": "foo"
        },
        "key4": 4
    },
    "key5": {
        "some_float": 2.3,
        "some_string": "bar"
    }
}
like image 100
Roland Deschain Avatar answered Oct 14 '25 11:10

Roland Deschain