Skip to content

Omit empty fields when serializing SlackFileObject - #478

Merged
kbasutkar-hubspot merged 2 commits into
masterfrom
kbasutkar/slack-file-object-non-absent
Oct 5, 2026
Merged

kbasutkar-hubspot merged 2 commits into
masterfrom
kbasutkar/slack-file-object-non-absent

Conversation

@kbasutkar-hubspot

Copy link
Copy Markdown
Contributor

Why

SlackFileObject is annotated @JsonInclude(NON_NULL), but NON_NULL doesn't treat an empty Optional as absent. A slack_file that references an uploaded file by ID is therefore serialized as:

"slack_file": {"url": null, "id": "F0C7JTV4QQ0"}

Slack rejects the whole message with invalid_blocks. This breaks both places a file can be referenced by ID: the top-level image block and an image element such as a card's hero_image (added in #473). We hit it in slack-integration when a Breeze reply carried a card whose hero image referenced an uploaded screenshot.

What

Switch to @JsonInclude(NON_ABSENT), the setting the rest of slack-base uses for Optional fields, so only the field that's set is written:

"slack_file": {"id": "F0C7JTV4QQ0"}

Tests

New SlackFileObjectSerializationTest asserts on the serialized JSON:

  • id-only and url-only SlackFileObjects omit the other field
  • an image block and a card hero_image referencing a file by ID serialize slack_file with only id, and no image_url
  • an id-only object round-trips

With the old NON_NULL, 4 of the 5 new tests fail. With the fix, the full slack-base suite passes (300 tests). I also installed this build locally and confirmed slack-integration's artifact card now serializes slack_file as {"id": ...}.

NON_NULL doesn't treat an empty Optional as absent, so an id-only slack_file
was sent as {"url": null, "id": "F..."}. Slack rejects that with
invalid_blocks, which broke image blocks and card hero images that reference
an uploaded file by ID. NON_ABSENT drops the empty field.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Comment on lines +24 to +25
assertThat(node.has("url")).isFalse();
assertThat(node.get("id").asText()).isEqualTo(FILE_ID);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we extract these and other magic strings into constants, since they are repeated in a few places?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 7ea51e2. Field names (id, url, image_url, slack_file, hero_image), the file ID/URL, alt text and card title are now constants, and the repeated SlackFileObject builder is pulled into an idOnlySlackFile() helper.

…stants

Addresses review feedback: field names, the file id and fixture text were
repeated across tests, so they now live in named constants alongside an
idOnlySlackFile() helper.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kbasutkar-hubspot
kbasutkar-hubspot merged commit 4168fb3 into master Oct 5, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants