Skip to content

Commit dd75669

Browse files
Support subclasses in lists in Union of List types (#1039)
1 parent 866eb2d commit dd75669

File tree

3 files changed

+62
-1
lines changed

3 files changed

+62
-1
lines changed

src/serializers/type_serializers/list.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,4 +116,8 @@ impl TypeSerializer for ListSerializer {
116116
fn get_name(&self) -> &str {
117117
&self.name
118118
}
119+
120+
fn retry_with_lax_check(&self) -> bool {
121+
self.item_serializer.retry_with_lax_check()
122+
}
119123
}

src/serializers/type_serializers/union.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,10 @@ impl TypeSerializer for UnionSerializer {
7575
exclude: Option<&PyAny>,
7676
extra: &Extra,
7777
) -> PyResult<PyObject> {
78-
// try the serializers in with error_on fallback=true
78+
// try the serializers in left to right order with error_on fallback=true
7979
let mut new_extra = extra.clone();
8080
new_extra.check = SerCheck::Strict;
81+
8182
for comb_serializer in &self.choices {
8283
match comb_serializer.to_python(value, include, exclude, &new_extra) {
8384
Ok(v) => return Ok(v),

tests/serializers/test_union.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,3 +454,59 @@ class Item(BaseModel):
454454
)
455455

456456
assert s.to_python(DBUser(name='John', password='secret')) == {'name': 'John'}
457+
458+
459+
def test_union_serializes_list_of_model_subclass_from_definition() -> None:
460+
class BaseModel:
461+
__slots__ = '__dict__', '__pydantic_fields_set__', '__pydantic_extra__', '__pydantic_private__'
462+
463+
def __init__(self, **kwargs: Any):
464+
for key, value in kwargs.items():
465+
setattr(self, key, value)
466+
467+
class User(BaseModel):
468+
name: str
469+
470+
class DBUser(User):
471+
password: str
472+
__pydantic_serializer__: ClassVar[SchemaSerializer]
473+
474+
DBUser.__pydantic_serializer__ = SchemaSerializer(
475+
core_schema.model_schema(
476+
DBUser,
477+
core_schema.model_fields_schema(
478+
{
479+
'name': core_schema.model_field(core_schema.str_schema()),
480+
'password': core_schema.model_field(core_schema.str_schema()),
481+
}
482+
),
483+
)
484+
)
485+
486+
class Item(BaseModel):
487+
price: float
488+
489+
s = SchemaSerializer(
490+
core_schema.definitions_schema(
491+
core_schema.union_schema(
492+
[
493+
core_schema.list_schema(core_schema.definition_reference_schema('User'), strict=False),
494+
core_schema.list_schema(core_schema.definition_reference_schema('Item'), strict=False),
495+
]
496+
),
497+
[
498+
core_schema.model_schema(
499+
User,
500+
core_schema.model_fields_schema({'name': core_schema.model_field(core_schema.str_schema())}),
501+
ref='User',
502+
),
503+
core_schema.model_schema(
504+
Item,
505+
core_schema.model_fields_schema({'price': core_schema.model_field(core_schema.float_schema())}),
506+
ref='Item',
507+
),
508+
],
509+
)
510+
)
511+
512+
assert s.to_python([DBUser(name='John', password='secret')]) == [{'name': 'John'}]

0 commit comments

Comments
 (0)