I want to use Pydantic 2 to export data to a Kafka Sub Queue and I need to export to JSON in a different model.
For example I have following object:
class obj(BaseModel):
resource: str
resourceid: int
resourceTime: datetime
name: str
option1: str
option2: int
{
"resource": "TEST",
"resourceid": "1234",
"resourceTime": "2024-09-03 00:00:00",
"option1": "test",
"option2": 23421,
"name": "test"
}
But I need to dump in this way:
{
"resource": "TEST",
"name": "test,
"resourceid": "1234",
"resourceTime": "2024-09-03 00:00:00",
"attributes": [
{
"name": "option1",
"value": "test",
},
{
"name": "option2",
"value": 23421
},
{
"name": "name",
"value": "test"
}
]
}
There is a possibility to use some functionality of Pydantic to achieve this?
Thanks.
You can use model_serializer
:
from datetime import datetime
from pydantic import BaseModel, Field, model_serializer
class obj(BaseModel):
resource: str
resourceid: int
resourceTime: datetime
name: str
option1: str = Field(exclude=True)
option2: int = Field(exclude=True)
@model_serializer(mode="wrap")
def _serialize(self, handler):
d = handler(self)
d["resourceid"] = str(d["resourceid"])
d["attributes"] = [
{
"name": "option1",
"value": self.option1
},
{
"name": "option2",
"value": self.option2
},
{
"name": "name",
"value": self.name
},
]
return d
o = obj.model_validate(
{
"resource": "TEST",
"resourceid": "1234",
"resourceTime": "2024-09-03 00:00:00",
"option1": "test",
"option2": 23421,
"name": "test"
}
)
print(o.model_dump())
UPD:
To achieve dynamic behavior you can do something like this:
class obj(BaseModel):
resource: str
resourceid: int
resourceTime: datetime
name: str
option1: str = Field(exclude=True)
option2: int = Field(exclude=True)
@model_serializer(mode="wrap")
def _serialize(self, handler):
d = handler(self)
d["resourceid"] = str(d["resourceid"])
attributes = [
{
"name": "name",
"value": self.name
},
]
for field_name in self.model_fields.keys():
if d.get(field_name) is None:
attributes.append(
{"name": field_name, "value": getattr(self, field_name)}
)
d["attributes"] = attributes
return d
This implementation will add to the attributes
all fields marked as exclude=True
plus the name
field