1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
|
from dataclasses import dataclass
from typing import Any
from apischema import alias, serialize, type_name
from apischema.json_schema import JsonSchemaVersion, definitions_schema
from apischema.objects import get_field, object_serialization
@dataclass
class Data:
id: int
content: str
@property
def size(self) -> int:
return len(self.content)
def get_details(self) -> Any:
...
# Serialization fields can be a str/field or a function/method/property
size_only = object_serialization(
Data, [get_field(Data).id, Data.size], type_name("DataSize")
)
# ["id", Data.size] would also work
def complete_data():
return [
..., # shortcut to include all the fields
Data.size,
(Data.get_details, alias("details")), # add/override metadata using tuple
]
# Serialization fields computation can be deferred in a function
# The serialization name will then be defaulted to the function name
complete = object_serialization(Data, complete_data)
data = Data(0, "data")
assert serialize(Data, data, conversion=size_only) == {"id": 0, "size": 4}
assert serialize(Data, data, conversion=complete) == {
"id": 0,
"content": "data",
"size": 4,
"details": None, # because get_details return None in this example
}
assert definitions_schema(
serialization=[(Data, size_only), (Data, complete)],
version=JsonSchemaVersion.OPEN_API_3_0,
) == {
"DataSize": {
"type": "object",
"properties": {"id": {"type": "integer"}, "size": {"type": "integer"}},
"required": ["id", "size"],
"additionalProperties": False,
},
"CompleteData": {
"type": "object",
"properties": {
"id": {"type": "integer"},
"content": {"type": "string"},
"size": {"type": "integer"},
"details": {},
},
"required": ["id", "content", "size", "details"],
"additionalProperties": False,
},
}
|