- Notifications
You must be signed in to change notification settings - Fork293
Add option to exclude a field using a callable#1535
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
base:main
Are you sure you want to change the base?
Add option to exclude a field using a callable#1535
Uh oh!
There was an error while loading.Please reload this page.
Conversation
codecovbot commentedNov 8, 2024 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
Codecov ReportAll modified and coverable lines are covered by tests ✅ 📢 Thoughts on this report?Let us know! |
please review |
codspeed-hqbot commentedNov 8, 2024 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
CodSpeed Performance ReportMerging#1535 willnot alter performanceComparing Summary
|
src/serializers/fields.rs Outdated
serializer: &CombinedSerializer, | ||
) -> PyResult<bool> { | ||
let py = value.py(); | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
think this should be called only if any condition is met, right? inside theif
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
I think we should probably handle this outside of theexclude_default
function as to decouple them for readability. We don't coupleexclude_default
withexclude_none
orexclude_unset
, so I think we should retain separation here as well!
Super exciting! Will give this a thorough review soon. Working on getting v2.10 out, and this will be included in v2.11 :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Would love to see an implementation on thepydantic
side as well - you can point to this branch.
Looks like a great start. I'm impressed with how simple this is going to be!
src/serializers/fields.rs Outdated
serializer: &CombinedSerializer, | ||
) -> PyResult<bool> { | ||
let py = value.py(); | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
I think we should probably handle this outside of theexclude_default
function as to decouple them for readability. We don't coupleexclude_default
withexclude_none
orexclude_unset
, so I think we should retain separation here as well!
I would anticipate that folks might want to set this at the |
Hello@sydney-runkle ! How do you do the implementation in |
I'm curious how the callable should work in the classModel(BaseModel):foo:strbar:list[str]foobaz:int>>>Model(foo="",bar= [],foobaz=1).model_dump(exclude_if=lambdafield:notfield){"foobaz":1} |
Yes, exactly this! Once we merge, we'll include in a minor It's just helpful to see the implementation on both sides before we merge the |
Yes, exactly this. That being said, I chatted with the team, and we decided that introducing this at the field level first makes sense, and we can follow with other config / runtime specs later. |
d7d7d0e
tob225197
CompareAlright,@sydney-runkle I created a PR pointing to this branch! |
Kevin-Mc-Callister commentedMar 3, 2025
Any news on this? |
joshorr commentedMar 31, 2025 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
@sydney-runkle It sounds like this feature did not get out in v2.11? Any news on when it might come out? |
@@ -2817,7 +2817,8 @@ class TypedDictField(TypedDict, total=False): | |||
validation_alias: Union[str, List[Union[str, int]], List[List[Union[str, int]]]] | |||
serialization_alias: str | |||
serialization_exclude: bool # default: False | |||
metadata: Dict[str, Any] | |||
exclude_if: Callable[[Any], bool] # default None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
exclude_if:Callable[[Any],bool]# default None | |
serialization_exclude_if:Callable[[Any],bool]# default None |
@@ -2827,7 +2828,8 @@ def typed_dict_field( | |||
validation_alias: str | list[str | int] | list[list[str | int]] | None = None, | |||
serialization_alias: str | None = None, | |||
serialization_exclude: bool | None = None, | |||
metadata: Dict[str, Any] | None = None, | |||
exclude_if: Callable[[Any], bool] | None = None, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
exclude_if:Callable[[Any],bool]|None=None, | |
serialization_exclude_if:Callable[[Any],bool]|None=None, |
@@ -2844,6 +2846,7 @@ def typed_dict_field( | |||
validation_alias: The alias(es) to use to find the field in the validation data | |||
serialization_alias: The alias to use as a key when serializing | |||
serialization_exclude: Whether to exclude the field when serializing | |||
exclude_if: Callable that determines whether to exclude a field during serialization based on its value. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
exclude_if:Callablethatdetermineswhethertoexcludeafieldduringserializationbasedonitsvalue. | |
serialization_exclude_if:Acallablethatdetermineswhethertoexcludethefieldwhenserializingbasedonitsvalue. |
@@ -2853,6 +2856,7 @@ def typed_dict_field( | |||
validation_alias=validation_alias, | |||
serialization_alias=serialization_alias, | |||
serialization_exclude=serialization_exclude, | |||
exclude_if=exclude_if, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
exclude_if=exclude_if, | |
serialization_exclude_if=serialization_exclude_if, |
@@ -2943,6 +2947,7 @@ class ModelField(TypedDict, total=False): | |||
validation_alias: Union[str, List[Union[str, int]], List[List[Union[str, int]]]] | |||
serialization_alias: str | |||
serialization_exclude: bool # default: False | |||
exclude_if: Callable[[Any], bool] # default: None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
exclude_if:Callable[[Any],bool]# default: None | |
serialization_exclude_if:Callable[[Any],bool]# default: None |
@@ -3171,7 +3179,8 @@ class DataclassField(TypedDict, total=False): | |||
validation_alias: Union[str, List[Union[str, int]], List[List[Union[str, int]]]] | |||
serialization_alias: str | |||
serialization_exclude: bool # default: False | |||
metadata: Dict[str, Any] | |||
exclude_if: Callable[[Any], bool] # default: None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
exclude_if:Callable[[Any],bool]# default: None | |
serialization_exclude_if:Callable[[Any],bool]# default: None |
@@ -3184,7 +3193,8 @@ def dataclass_field( | |||
validation_alias: str | list[str | int] | list[list[str | int]] | None = None, | |||
serialization_alias: str | None = None, | |||
serialization_exclude: bool | None = None, | |||
metadata: Dict[str, Any] | None = None, | |||
exclude_if: Callable[[Any], bool] | None = None, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
exclude_if:Callable[[Any],bool]|None=None, | |
serialization_exclude_if:Callable[[Any],bool]|None=None, |
@@ -3210,6 +3220,7 @@ def dataclass_field( | |||
validation_alias: The alias(es) to use to find the field in the validation data | |||
serialization_alias: The alias to use as a key when serializing | |||
serialization_exclude: Whether to exclude the field when serializing | |||
exclude_if: Callable that determines whether to exclude a field during serialization based on its value. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
exclude_if:Callablethatdetermineswhethertoexcludeafieldduringserializationbasedonitsvalue. | |
serialization_exclude_if:Acallablethatdetermineswhethertoexcludethefieldwhenserializingbasedonitsvalue. |
@@ -3223,6 +3234,7 @@ def dataclass_field( | |||
validation_alias=validation_alias, | |||
serialization_alias=serialization_alias, | |||
serialization_exclude=serialization_exclude, | |||
exclude_if=exclude_if, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
exclude_if=exclude_if, | |
serialization_exclude_if=serialization_exclude_if, |
@@ -80,6 +95,7 @@ fn exclude_default(value: &Bound<'_, PyAny>, extra: &Extra, serializer: &Combine | |||
} | |||
} | |||
} | |||
// If neither condition is met, do not exclude the field |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Lets avoid diff noise:
// If neither condition is met, do not exclude the field |
Uh oh!
There was an error while loading.Please reload this page.
Change Summary
This PR aims to add support for excluding field from serialization based on condition. As@davidhewitt suggested I added a new
exclude_if
argument at field level, which is callable that checks if the field value meets a condition. However, in this pydanticissue David suggested to useskip_serializing_if
from Rust's serde, I could't find a way to use it due that serialization is being doing a loop for each field usingserialize_map
.Related issue number
pydantic/pydantic#10728
Checklist
pydantic-core
(except for expected changes)Selected Reviewer:@sydney-runkle