Repository navigation
fix: keep nested None and passed empty lists in update payloads - #1221
Open
dheerajitbhu wants to merge 1 commit into
Open
dheerajitbhu wants to merge 1 commit into
dheerajitbhu wants to merge 1 commit into
Conversation
vdusek
reviewed
Nov 10, 2026
| @staticmethod | ||
| def _clean_json_payload(data: dict) -> dict: | ||
| """Remove None values and empty nested dicts from an API request payload. | ||
| """Remove unset top-level fields and empty nested dicts from an API request payload. |
Contributor
There was a problem hiding this comment.
Question: a nested None the caller passes is kept now, but a nested {} they pass is still removed, so tagged_builds={'beta': {}} is dropped. Is that intended? The JS client sends both as given.
✍️ Drafted by Claude Code
Comment on lines
+158
to
+160
| A top-level `None` means the caller did not pass the argument, so the field is left out. `None` inside | ||
| a nested value the caller passed is kept and sent as `null`, so for example | ||
| `tagged_builds={'beta': None}` sends `{"taggedBuilds": {"beta": null}}` and removes the tag. |
Contributor
There was a problem hiding this comment.
Nit: the docstring can use the full 120-character line length.
Suggested change
| A top-level `None` means the caller did not pass the argument, so the field is left out. `None` inside | |
| a nested value the caller passed is kept and sent as `null`, so for example | |
| `tagged_builds={'beta': None}` sends `{"taggedBuilds": {"beta": null}}` and removes the tag. | |
| A top-level `None` means the caller did not pass the argument, so the field is left out. `None` inside | |
| a nested value the caller passed is kept and sent as `null`, so for example `tagged_builds={'beta': None}` | |
| sends `{"taggedBuilds": {"beta": null}}` and removes the tag. |
✍️ Drafted by Claude Code
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #1136
Problem
_clean_json_payloadstrippedNoneat every nesting level and then dropped dicts that became empty. Soactor.update(tagged_builds={'beta': None})sent{}and the tag was never removed, even though theupdate()docstring and the API docs saynullremoves it. Separately,schedule.update(actions=[])andversion.update(env_vars=[], source_files=[])turned the empty list intoNonebefore the filter, so those updates were silently ignored.Change
_clean_json_payloadnow dropsNoneonly at the top level (an unset argument) and keepsNoneinside values the caller passed. Empty nested dicts are still removed at every level, because sub-models dumped withexclude_none=Trueproduce them when all their fields are unset (e.g.exampleRunInput).ScheduleClient(Async).updatepassesactionsthrough as given;ActorVersionClient(Async).updateonly convertsenv_vars/source_fileswhen they are notNone, so[]is sent as[].null(clearing fields likegeneralAccess) is out of scope here and stays with Letupdate()methods clear a field by sendingnull#1135, as the issue says.Tests
test__clean_json_payloadcases updated for the new contract (nestedNonekept, nested empty dicts removed, lists kept as passed).tagged_builds={'beta': None}→{"taggedBuilds": {"beta": null}},schedule.update(actions=[])→{"actions": []},version.update(env_vars=[], source_files=[])→{"envVars": [], "sourceFiles": []}. 15 of them fail onmasterand pass with the fix.poe lintandpoe type-checkare green.Note: the branch is based on 41c6f39 (6 commits behind
master, none touching these files) because my fork can't receive upstream workflow-file changes; happy to rebase if needed.Disclosure: I maintain a few Apify Store actors, and this change was prepared with AI assistance and reviewed and tested by me.