Skip to content

Clear chat.update attachments/blocks via type-level @JsonSerialize - #487

Merged
yyakhnytsia merged 9 commits into
HubSpot:masterfrom
yyakhnytsia:yyakhnytsia/chat-update-clear-flags-via-jsonserialize
Oct 16, 2026
Merged

yyakhnytsia merged 9 commits into
HubSpot:masterfrom
yyakhnytsia:yyakhnytsia/chat-update-clear-flags-via-jsonserialize

Conversation

@yyakhnytsia

Copy link
Copy Markdown
Contributor

chat.update: clear attachments/blocks via type-level @JsonSerialize

Why

ChatUpdateMessageParams is @JsonInclude(NON_EMPTY), so an empty attachments/blocks
list is dropped and Slack's chat.update keeps the old value — there's no way to actively
clear a field. The shouldClearAttachments/shouldClearBlocks flags were added for this, but
the first implementation emitted [] via a BeanSerializerModifier registered on
ObjectMapperUtils.mapper(). Consumers serialize request bodies with their own ObjectMapper
(e.g. slack-integration uses JsonUtils.MAPPER), which never saw that modifier — so the flags
silently did nothing on the real request path.

How

Attach the clear logic to the type with @JsonSerialize(using = ChatUpdateMessageParamsSerializer.class)
instead of a mapper-level modifier. A type annotation is honored by any ObjectMapper, so the
flags now emit attachments: [] / blocks: [] regardless of which mapper serializes the params.
The serializer reproduces the existing NON_EMPTY behavior for every field, so with both flags
at their false default the output is byte-for-byte unchanged (existing callers unaffected).

Removes the now-dead BeanSerializerModifier/ForceEmitPropertyWriter and the ObjectMapperUtils
registration.

Tests

ChatUpdateMessageParamsSerializationTest: omit-when-off, emit-[]-when-clearing, flag
independence, flags don't leak into the payload, full-field drift guard, and — the key one —
itHonorsClearFlagsUnderAForeignObjectMapper, which serializes with a plain mapper (not
ObjectMapperUtils.mapper()) and proves [] is still emitted. Full slack-base suite green;
SpotBugs clean.

Yurii Yakhnytsia and others added 8 commits October 14, 2026 18:01
Replace the BeanSerializerModifier approach (registered on ObjectMapperUtils.mapper())
with a @JsonSerialize serializer on ChatUpdateMessageParams, so the shouldClearAttachments/
shouldClearBlocks flags emit `[]` under ANY ObjectMapper — including a consumer's own mapper
that never touches ObjectMapperUtils.mapper().

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the BeanSerializerModifier approach (registered on ObjectMapperUtils.mapper())
with a @JsonSerialize serializer on ChatUpdateMessageParams, so the shouldClearAttachments/
shouldClearBlocks flags emit `[]` under ANY ObjectMapper — including a consumer's own mapper
that never touches ObjectMapperUtils.mapper().

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…s-via-jsonserialize' into yyakhnytsia/chat-update-clear-flags-via-jsonserialize

# Conflicts:
#	slack-base/src/test/java/com/hubspot/slack/client/methods/params/chat/ChatUpdateMessageParamsSerializationTest.java
…s-via-jsonserialize' into yyakhnytsia/chat-update-clear-flags-via-jsonserialize

# Conflicts:
#	slack-base/src/test/java/com/hubspot/slack/client/methods/params/chat/ChatUpdateMessageParamsSerializationTest.java
…s-via-jsonserialize' into yyakhnytsia/chat-update-clear-flags-via-jsonserialize

# Conflicts:
#	slack-base/src/test/java/com/hubspot/slack/client/methods/params/chat/ChatUpdateMessageParamsSerializationTest.java
…s-via-jsonserialize' into yyakhnytsia/chat-update-clear-flags-via-jsonserialize

# Conflicts:
#	slack-base/src/test/java/com/hubspot/slack/client/methods/params/chat/ChatUpdateMessageParamsSerializationTest.java
…s-via-jsonserialize' into yyakhnytsia/chat-update-clear-flags-via-jsonserialize
@Viktor-Pelepiak

Copy link
Copy Markdown
Contributor

@yyakhnytsia Left a few comments

Comment on lines +277 to +282
JsonNode json = foreignMapper.valueToTree(
ChatUpdateMessageParams
.builder()
.setChannelId("C123")
.setTs("1790587670.603089")
.setText("testText")

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.

these and others strings are repeated throw the test, Should we extract them to the constants?

Comment on lines +33 to +41
.builder()
.setChannelId("C123")
.setTs("1790587670.603089")
.setText("testText")
.addFileIds("F0C4SK2P1EZ")
.setAsUser(true)
.setShouldLinkNames(false)
.setParse("full")
.addAttachments(Attachment.builder().setText("attachment").build())

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.

Same here. Actually even the same constants - probably it may be useful to create a TestConstants class to use it through all tests

Comment on lines +64 to +68
gen.writeArrayFieldStart(FILE_IDS_FIELD);
for (String fileId : params.getFileIds()) {
gen.writeString(fileId);
}
gen.writeEndArray();

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.

what do you think about extracting this block into separate method to decrease nesting level and improve readability?

@yyakhnytsia
yyakhnytsia merged commit be5052d into HubSpot:master Oct 16, 2026
1 check 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